У меня был встроенный частично специализированный шаблонный код, работающий с VS 2015, пока я не обнаружил, что it was not standards-compliant. Я хочу, чтобы это было так, что я искал свой код для преодоления прежней проблемы, а также that one и теперь ударил по жесткой стене.Как заполнить массив содержимым пакета параметров шаблона?
Использование вариативных шаблонов и частичной специализации Я хотел бы заполнить массив во время компиляции с учетом фиксированного набора параметров.
То, что я хочу достичь, также похоже на this answer, но мне не удалось заставить его работать.
Рассмотрим следующую программу:
#include <cstdlib>
template <typename T, std::size_t Size>
struct Array;
template <typename T, std::size_t Size, std::size_t Iteration, typename ...Args>
struct ArrayFiller {
inline
static void fill(Array<T, Size>& a, const Args&... args) {
ArrayFiller<T, Size, Iteration, Args...>::fill_recursive(a, args...);
}
inline
static void fill_recursive(Array<T, Size>& a, const T& i, const Args&... args) {
a.data[Size - Iteration - 1] = i;
ArrayFiller<T, Size, Iteration - 1>::fill_recursive(a, args...);
}
};
template <typename T, std::size_t Size>
struct ArrayFiller<T, Size, 0> {
inline
static void fill_recursive(Array<T, Size>& a, const T& i) {
a.data[Size - 1] = i;
}
};
template <typename T, std::size_t Size>
struct Array {
T data[Size];
template <typename ...Args>
Array(const Args&... args) {
ArrayFiller<T, Size, Size - 1, Args...>::fill(*this, args...);
}
};
int main() {
Array<int, 2> c(42, -18);
return 0;
}
... и начало его g++ -std=c++14 -pedantic -Wall -Wextra
вывода (в версии 5.3.0):
main.cpp: In instantiation of ‘static void ArrayFiller<T, Size, Iteration, Args>::fill(Array<T, Size>&, const Args& ...) [with T = int; long unsigned int Size = 2ul; long unsigned int Iteration = 1ul; Args = {int, int}]’:
main.cpp:34:54: required from ‘Array<T, Size>::Array(const Args& ...) [with Args = {int, int}; T = int; long unsigned int Size = 2ul]’
main.cpp:39:28: required from here
main.cpp:10:65: error: no matching function for call to ‘ArrayFiller<int, 2ul, 1ul, int, int>::fill_recursive(Array<int, 2ul>&, const int&, const int&)’
ArrayFiller<T, Size, Iteration, Args...>::fill_recursive(a, args...);
^
main.cpp:14:17: note: candidate: static void ArrayFiller<T, Size, Iteration, Args>::fill_recursive(Array<T, Size>&, const T&, const Args& ...) [with T = int; long unsigned int Size = 2ul; long unsigned int Iteration = 1ul; Args = {int, int}]
static void fill_recursive(Array<T, Size>& a, const T& i, const Args&... args) {
^
main.cpp:14:17: note: candidate expects 4 arguments, 3 provided
В основном компилятор жалуется, что нет поскольку из того, что я понимаю, пакет параметров расширяется либо слишком «скоро», либо слишком «поздно» в моей логике: аргумент const T& i
в рекурсивном вызове вызывает расширение.
Как вы его исправить?
Меня также интересуют альтернативные/лучшие/чистые решения.
Зачем вам нужен вариационный шаблон, когда будет создан конструктор constexpr с инициализационным списком? – SergeyA
Да, я не уверен, почему вы не просто используете 'std :: array', который поддерживает именно этот синтаксис ... Это не« заполнение »массива, что подразумевает генерирование значений; он просто инициализирует его из предоставленных значений. И когда стандартная библиотека C++ уже предоставила необходимое вам колесо, обычно это плохая идея, чтобы попытаться изобрести ее самостоятельно. –
@SergeyA: не могли бы вы рассказать? Это то, о чем говорит Витторио? Извините, мне не так удобно с C++, как с другими инструментами. – dummydev