Как написать функции шаблона CPP, которые рекурсивны по длине массива аргументов
Скажем, я хочу написать функцию
arrfill<N>
который заполняет массив длины. Ниже представлена реализация шаблона, который я пробовал.
template<typename T>
bool arrfill(T arr[0], T v){;}
template<size_t N, typename T>
void arrfill(T arr[N], T v){
arr[0] = v;
arrfill<N-1>(arr+1, v);
}
int main(int argc, char const *argv[])
{
bool barr[4];
arrfill<4>(barr, true);
}
Однако это не будет компилироваться, поскольку создание экземпляра шаблона не завершится в том случае, если
N
является
0
и превысит его максимальную глубину.
Похоже, что компиляторы не примут размер массива в подписи в качестве типа аргумента. Интересно, как правильно это указать?
2 ответа
Вы постепенно приходите в упадок.
template<typename T>
bool arrfill(T (&arr)[1], T v){arr[0]=v;}
template<size_t N, typename T>
void arrfill(T (&arr)[N], T v){
arr[0] = v;
arrfill(*reinterpret_cast<T(*)[N-1]>(arr+1), v);
}
который является UB, который работает во всех компиляторах.
Действительно, используйте пачки и складные.
template<size_t N, typename T,std::size_t...Is>
void arrfill(T (&arr)[N], T v,std::index_sequence<Is...>){
((void)(arr[Is]=v),...);
}
template<size_t N, typename T>
void arrfill(T (&arr)[N], T v){
arrfill(arr, v, std::make_index_sequence<N>{});
}
или просто используйте std fill_n
Я пришел с решением, определив новый класс, кодирующий информацию о длине. Но мне интересно, самый ли это изящный способ.
template<size_t N>
struct intClass{};
template<typename T>
bool arrfill(T arr[0], T v, intClass<0>){;}
template<size_t N, typename T>
void arrfill(T arr[N], T v, intClass<N>){
arr[0] = v;
arrfill(arr+1, v, intClass<N-1>());
}
template<size_t N, typename T>
void arrfill(T arr[N], T v){
arrfill(arr,v, intClass<N>());
}