Considering the following example (I posted it for several different questions today) :
#include <iostream>
#include <vector>
#include <array>
#include <type_traits>
// Version A
template<typename T>
constexpr unsigned int f(const T&)
{
return 1;
}
// Version B
template<typename... T1, template<typename...> class T>
constexpr unsigned int f(const T<T1...>&)
{
return 2;
}
// Version C
template<typename T1, template<typename, unsigned int...> class T, unsigned int... N>
constexpr unsigned int f(const T<T1, N...>&)
{
return 3;
}
// Main
int main(int argc, char* argv[])
{
std::integral_constant<int, f(double())> a;
std::integral_constant<int, f(std::vector<double>())> b;
std::integral_constant<int, f(std::array<double, 3>())> c;
std::cout<<a<<b<<c<<std::endl; // The goal is to return 123
return 0;
}
This code does not compile and returns the following compilation error :
temporary of non-literal type 'std::vector<double>' in a constant expression
How to modify this code in order to compile it ?
Note : the goal is to convert a type that will be taken by the first version of the function to 1, a type that will be taken by the second version of the function to 2, etc…
You cannot use temporary vector when defining constant:
The thing is that compiler could possibly omit
vectorcreation, if vector’s only purpose was passing to the constant expression function, but actually it cannot, because vector is not literal type.std::arrayis only a thing wrapper above c array, it has trivial constructor and destructor. As double is also literal type, array of doubles becomes literal.Note, however, that if you define
you would not be able to use constructs:
either, while
still would be possible.