How can I tell if a template is an alias pattern?
Given the "normal" template:
template<typename> struct Normal;
and the alias pattern:
template<typename>
using Alias = void;
How can I differentiate between the two by setting a template template parameter?
So, ideally, I want the following to compile:
int main() {
static_assert( is_alias_template<Alias>::value, "");
static_assert(! is_alias_template<Normal>::value, "");
}
source to share
One possible approach is to use this:
Alias ββtemplates are never deduced by subtracting the template argument when the template template parameter is deduced.
So with a type like
template<
typename T,
template<typename...> class Template
>
struct instantiated_from
: std::false_type {};
template<
template<typename...> class Template,
typename... Arguments
>
struct instantiated_from<Template<Arguments...>, Template>
: std::true_type {};
we can be sure that when we pass Alias<int>
as the first template parameter and Alias
as the second, then the compiler will not choose specialization. This immediately gives us:
template<
template<typename...> class Template,
typename... Args
>
struct is_alias_template
: std::integral_constant<
bool,
! instantiated_from<Template<Args...>, Template>::value
>
{};
With this we can - given some suitable template arguments - determine whether a template is an alias template or not:
int main() {
static_assert( is_alias_template<Alias, int>::value, "");
static_assert(! is_alias_template<Normal, int>::value, "");
static_assert( is_alias_template<Alias, Alias<int>>::value, "");
static_assert( is_alias_template<Alias, Normal<int>>::value, "");
static_assert(! is_alias_template<Normal, Alias<int>>::value, "");
static_assert(! is_alias_template<Normal, Normal<int>>::value, "");
}
The main drawback here, of course, is that you need to know the set of matching template arguments. Just guessing (or using int
) won't work, for example, with templates with a fixed number (> 1) of template parameters.
Further, this does not work with templates (aliases or not) that have non-burn type template parameters (or template).
source to share