This form of the template template parameter is only allowed in C ++ 17:
template < // v---------- typename here not allowed template <typename> typename TT, typename T, std::enable_if_t<std::is_same<TT<T>, Foo<T>>::value, int> = 0 > Foo<T> create() { return Foo<T>(T()); }
You should replace typename with a class pointer:
template <
In C ++ 17, both are compiled and equivalent.
To your syntax Foo<int> foo = create<Foo<int>>(); worked, you just need to do this:
template <typename T> T create() { return T{}; }
If you want to limit which type can be sent, you must create a type character:
// default case has no typedef template<typename> struct first_param {}; // when a template is sent, define the typedef `type` to be equal to T template<template<typename> class TT, typename T> struct first_param<TT<T>> { using type = T; }; // template alias to omit `typename` everywhere we want to use the trait. template<typename T> using first_param_t = typename first_param<T>::type;
Then use your tag:
template < typename T, void_t<first_param_t<T>>* = nullptr >
You can implement void_t as follows:
template<typename...> using void_t = void;
Live at coliru
source share