Проблема: я столкнулся с многочисленными дублирующими функциями для поддержки различных типов почти идентичных массивов. Например, функция Foo может быть доступна в следующих версиях:Конструктор шаблонов
void foo (int v); // single value, 99% of all use cases.
void foo (std::initializer_list<int> v);
void foo (const std::vector<int> &v);
void foo (int *v, int size);
Это дублирование беспокоит меня. Я хотел бы иметь одну функцию foo, которую можно вызывать с любыми типами данных, подобными массиву (с одним значением, очевидно, рассматриваемым как массив размером 1).
Возможные решения включают в себя:
- Всегда использовать векторную версию. Это накладывает некоторые накладные расходы на распределение памяти при каждом использовании, и поскольку 99% моих применений предназначены для одиночных значений, я считаю это нежелательным.
- Имейте интерфейс, определяющий пару итераторов. При попытке вызвать функцию для одного значения это снова падает.
- Имейте абстракцию для массивных данных, которые могут обрабатывать все требуемые типы ввода. Это многообещающий подход, но я столкнулся с некоторыми неприятностями ...
. Моя реализация называется mem_range, которая представляет собой векторный интерфейс (включающий только операции, которые не изменяют размер вектора, очевидно). Предполагается, что различные типы массивов обрабатываются через различные конструкторы mem_range.
У меня проблема с конструктором, который должен принять std :: array. Проблема заключается в размере массива, который является частью определения шаблона - я не могу понять, как создать конструктор, который будет принимать массивы любого размера.
template<typename T>
class mem_range {
public:
mem_range (T *begin, T *end) { } // ok
mem_range (std::vector<T> &vec) { } // ok
template<int array_size>
mem_range<array_size> (std::array<T, array_size> &arr) { } // not ok
}
Последний конструктор дает "ошибка C2988: неузнаваемый шаблон декларация/определение" на MSVC2015. Сейчас я пережил немало вариаций, но ничего не делает компилятор счастливым.
Просто чтобы быть ясно, на основе ответов, которые я читал на подобные вопросы здесь, на StackOverflow:
- Изменение размеров массивов, как данные в любом случае не в области. Если бы я хотел эту возможность, я бы просто передал std :: vector.
- Я знаю, что есть много вопросов с похожими названиями. Ни у кого из них, кажется, нет достойных ответов, обычно не получающих ничего, кроме «зачем вы этого хотите?».
Я пытаюсь сделать эту работу над MSVC2015 и современным GCC, поэтому C++ 14/17 в порядке (насколько поддерживается).
Когда вы пишете код, напишите его как можно проще и понятнее - не беспокойтесь об оптимизации до тех пор, пока у вас не будет фактического набора данных для профиля. Беспокойство о стоимости создания массива из 1 элемента, вероятно, не будет чем-то, что сделает или сломает вашу программу - удержание ошибок, построив их просто, тем не менее, может спасти вас от некоторых серьезных головных болей позже. – xaxxon
Это система 300 000 строк, используемая для высокопроизводительного научного анализа, и производительность заметно снизилась, когда я попытался объединить все эти функции в одну (векторную) версию. Я работаю над этим почти 20 лет, надеюсь, что это будет «позже» в вашей книге ... –
«Это накладывает некоторые накладные расходы на распределение памяти при каждом использовании, и поскольку 99% моих применений предназначены для одиночных значений Я нахожу это нежелательным ». на самом деле не передает эту информацию. – xaxxon