Combining template parameter packages for a unary argument

Although, say, std::add_pointer is unary, the following code is accepted by both GCC 7.0.0 (20160608) and Clang 3.9.0:

 template <typename ...Ts> struct tc1 { using a = std::add_pointer<Ts...>; }; 

However, although the following code has been accepted by the Clan, it is rejected by the GCC:

 template <typename ...Ts> struct tc2 { template <typename ...Us> using b = std::add_pointer<Ts...,Us...>; }; 

Is this valid C ++? Syntactically, I could imagine that a comma is a problem when packages are empty, but it seems to be deleted in other cases; for example, std::common_type takes zero or more arguments, and the following does not present a problem for any compiler:

 template <typename ...Ts> struct tc3 { template <typename ...Us> using c = std::common_type<Ts...,Us...>; }; 
+8
c ++ c ++ 11 templates g ++ clang ++
source share
1 answer

You can use this code for any number of arguments to the tc3<1 or more>::a<zero or more> template, on GCC and Clang:

 #include <type_traits> struct A { template<typename ...Args> A(Args ... args) {} }; template <typename T, typename ...Ts> struct tc3 { template <typename ...Us> using c = std::add_pointer<T(Ts...,Us...)>; }; int main() { typedef tc3<A, int, float>::template c<unsigned, double>::type ptr;// A(*)(int,float,unsigned,double) typedef tc3<A>::template c<>::type ptr2; // A(*)() typedef tc3<bool>::template c<int, int>::type ptr3; // bool(*)(int,int) typedef std::add_pointer<bool(int, int)>::type ptr4; // bool(*)(int,int) return 0; } 

However, although the following code has been accepted by the Clan, it is rejected by the GCC:

This following code was accepted by the Clan only until its creation, but after an error:

 template <typename ...Ts> struct tc2 { template <typename ...Us> using b = std::add_pointer<Ts...,Us...>; }; 

std::add_pointer<> can only take one tamplte argument: http://en.cppreference.com/w/cpp/types/add_pointer

 template< class T > struct add_pointer; 

It can take more than one argument only in the internal namespace part or in another:

Possible implementation:

 namespace detail { template< class T, bool is_function_type = false > struct add_pointer { using type = typename std::remove_reference<T>::type*; }; template< class T > struct add_pointer<T, true> { using type = T; }; template< class T, class... Args > struct add_pointer<T(Args...), true> { using type = T(*)(Args...); }; template< class T, class... Args > struct add_pointer<T(Args..., ...), true> { using type = T(*)(Args..., ...); }; } // namespace detail template< class T > struct add_pointer : detail::add_pointer<T, std::is_function<T>::value> {}; 

This is done to support this code:

 typedef std::add_pointer<bool(int, int)>::type ptr4; // bool(*)(int,int) 
+1
source share

All Articles