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, while the following code is accepted by Clang, it is rejected by 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 the comma is a problem when packs are empty, but presumably it is elided on other occasions; for example, std::common_type
accepts zero or more arguments, and the following presents no problem for either compiler:
template <typename ...Ts>
struct tc3 {
template <typename ...Us>
using c = std::common_type<Ts...,Us...>;
};
You can use this code for any number of template arguments tc3<1 or more>::a<zero or more>
, 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, while the following code is accepted by Clang, it is rejected by GCC:
This following code is accepted by Clang only before instantinationed, but after there is error:
template <typename ...Ts>
struct tc2 {
template <typename ...Us>
using b = std::add_pointer<Ts...,Us...>;
};
std::add_pointer<>
can take only one tamplte argument: http://en.cppreference.com/w/cpp/types/add_pointer
template< class T >
struct add_pointer;
More than one argument it can take only in internal namespace
detail or in some else:
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With