Can a variable template be used to declare another variable template?

With variable templates included in C ++ 14 (and Clang already supporting them) and a proposal for standard is_same_v and similar types, I figured it was possible to create new type traits like this:

 template<typename T> constexpr bool is_const_and_volatile{std::is_const_v<T> && std::is_volatile_v<T>}; 

Alas, this leads to errors equivalent to the following SSCCE ( this one contains everything below):

 #include <type_traits> template<typename T> constexpr bool is_pointer{std::is_pointer<T>::value}; template<typename T> constexpr bool foo{is_pointer<T>}; int main() { //foo<int *>; } 

When reading a line in main Clang, it spits out the following:

warning: the variable is_pointer<type-parameter-0-0> has an internal relationship but is not defined

It looks specific to me (note that changing T to int * in foo works fine). Uncommenting the line in main to instantiate foo gives this (again, from T to int * works fine):

error: constexpr constant foo<int *> must be initialized with a constant expression

However, replacing foo with the following old syntax makes both instances work fine:

 constexpr bool foo{std::is_pointer<T>::value}; 

Is there something I am missing in variable templates? Is there a way to create new variable templates with them, or am I forced to use the old syntax to create new ones and use syntactic sugar only when using them for other code?

+8
c ++ c ++ 14 variable-templates
source share
2 answers

Your code is valid and accepted by clang SVN. The communication error was caused by clang error 17846 , in which I fixed a couple of days ago .

+3
source share

The following seems to work:

 #include <type_traits> #include <iostream> template<typename T> struct test { static constexpr bool is_pointer{std::is_pointer<T>::value}; }; template<typename T> constexpr bool test<T>::is_pointer; template<typename T> constexpr bool foo{test<T>::is_pointer}; int main() { std::cout << foo<bool>; std::cout << foo<bool*>; } 

Living example

Although it handles the same warning if it is used in the context of constexpr , so I suppose it really doesn't work.

 // Fail template<typename T> typename std::enable_if<foo<T>, void>::type bar() { } int main() { bar<bool*>(); } main.cpp:21:5: error: no matching function for call to 'bar' bar<bool*>(); ^~~~~~~~~~ main.cpp:16:45: note: candidate template ignored: substitution failure [with T = bool *]: non-type template argument is not a constant expression typename std::enable_if<foo<T>, void>::type bar() 

It stops complaining if you give foo an explicit type:

 template<typename T> typename std::enable_if<foo<bool*>, void>::type bar() { } 

Or just use test<T>::is_pointer directly:

 template<typename T> typename std::enable_if<test<T>::is_pointer, void>::type bar() { } 
0
source share

All Articles