Reputation: 703
The following program gives errors in both g++ and clang...
#include <iostream>
#include <utility>
using namespace std;
//Since C++17 one can use fold expression to calculate factorial:
template <class T, T N, class I = std::make_integer_sequence<T, N>>
struct factorial;
template <class T, T N, T... Is>
struct factorial<T,N,std::index_sequence<T, Is...>> {
static constexpr T value = (static_cast<T>(1)* ... *(Is + 1));
};
int main(int argc, char** argv) {
std::cout << factorial<int, 5>::value << std::endl;
return 0;
}
Errors listed in gcc are as follows:
error: type/value mismatch at argument 1 in template parameter list for 'template<long unsigned int ..._Idx> using index_sequence = std::integer_sequence<long unsigned int, _Idx ...>'
24 | struct factorial<T,N,std::index_sequence<T, Is...>> {
| ^~~
note: expected a constant of type 'long unsigned int', got 'T'
error: template argument 3 is invalid
24 | struct factorial<T,N,std::index_sequence<T, Is...>> {
| ^~
In function 'int main(int, char**)':
error: incomplete type 'factorial<int, 5>' used in nested name specifier
31 | std::cout << factorial<int, 5>::value << std::endl;
| ^~~~~
Clang errors are as follows:
error: template argument for non-type template parameter must be an expression
struct factorial<T,N,std::index_sequence<T, Is...>> {
^
D:\Programs\msys64\mingw64\include\c++\10.1.0\utility:344:22: note: template parameter is declared here
template<size_t... _Idx>
^
main.cpp:32:18: error: implicit instantiation of undefined template 'factorial<int, 5, std::integer_sequence<int, 0, 1, 2, 3, 4> >'
std::cout << factorial<int, 5>::value << std::endl;
^
main.cpp:22:8: note: template is declared here
struct factorial;
^
This example is shown in many sites.
Request somebody to help me correcting it.
Upvotes: 2
Views: 286
Reputation: 170299
You used the wrong type for your result object.
std::index_sequence
is a template that accepts only a pack of std::size_t
. It doesn't accept a type parameter, because the type is fixed. It is an alias template for std::integer_sequence<std::size_t, Ints...>
.
So you trying to specify a type as its the first argument in std::index_sequence<T,...>
is wrong.
What you want is the more general type trait std::integer_sequence
, making your specialization into this
template <class T, T N, T... Is>
struct factorial<T,N,std::integer_sequence<T, Is...>> {
static constexpr T value = (static_cast<T>(1)* ... *(Is + 1));
};
Upvotes: 2