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..., ...); }; }
This is done to support this code:
typedef std::add_pointer<bool(int, int)>::type ptr4;