I've got a recursive variadic template function that I can use to evaluate its arguments at compile time, to make sure none of them are larger than a specified maximum value:
#include <type_traits>
// base-case
template <int MaxVal, typename T>
constexpr T returnZeroIffValuesAreNotTooBig(const T t)
{
return (t>MaxVal)?1:0;
}
// recursive-case
template <int MaxVal, typename T, typename... Rest> constexpr T returnZeroIffValuesAreNotTooBig(const T t, Rest&&... rest)
{
return returnZeroIffValuesAreNotTooBig<MaxVal>(t)
+ returnZeroIffValuesAreNotTooBig<MaxVal>(std::forward<Rest>(rest)...);
}
int main(int argc, char ** argv)
{
static_assert(returnZeroIffValuesAreNotTooBig<6>(1,2,3)==0, "compiles (as expected)");
static_assert(returnZeroIffValuesAreNotTooBig<6>(1,2,3,4,5,6,7)==0, "generates compile-time error (as expected, because one of the args is greater than 6)");
return 0;
}
... so far, so good, all of the above works fine for me.
Now I want to use that function in my class's variadic constructor:
template<int MaxVal> class MyClass
{
public:
template<typename ...Vals> constexpr explicit MyClass(Vals&&... vals)
{
// verify at compile-time that all values in (vals) are <= MaxVal
static_assert(returnZeroIffValuesAreNotTooBig<MaxVal>(std::forward<Vals>(vals)...)==0, "why doesn't this compile?");
}
};
int main(int argc, char ** argv)
{
MyClass<5> b(1,2,3,4); // should compile, but doesn't!?
return 0;
}
... this won't compile; instead I always get this error:
$ g++ -std=c++11 ./test.cpp
./test.cpp:12:80: error: static_assert expression is not an integral constant
expression
...returnZeroIffValuesAreNotTooBig<MaxVal>(std::forward<Vals>(vals)...)==0...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~
./test.cpp:21:15: note: in instantiation of function template specialization
'MyClass<5>::MyClass<int, int, int, int>' requested here
MyClass<5> b(1,2,3,4);
^
1 error generated.
... apparently my perfect forwarding is imperfect, and that is preventing the returnZeroIffValuesAreNotToBig
function from being evaluated at compile-time? Can someone give me a hint as to what I need to differently in order to get this to work?
Aucun commentaire:
Enregistrer un commentaire