No, it cannot be solved (not without changing the design significantly at least). The problem is that template alias names are not deduced, as mentioned in paragraph 14.5.7/2 of the C++11 Standard:
When a template-id refers to the specialization of an alias template, it is equivalent to the associated type
obtained by substitution of its template-arguments for the template-parameters in the type-id of the alias
template. [ Note: An alias template name is never deduced.—end note ]
The paragraph also provides an example:
[ Example:
template<class T> struct Alloc { / ... / };
template<class T> using Vec = vector<T, Alloc<T>>;
Vec<int> v; // same as vector<int, Alloc<int>> v;
...
template<template<class> class TT>
void f(TT<int>);
f(v); // error: Vec not deduced <=== Relevant
...
—end example ]
In your concrete case, the problem is that when trying to match the partial specialization, the compiler won't deduce that your type is an instantiation of foo_alt
(since foo_alt
is the name of an alias template), and the primary template gets picked.
If you want to use alias templates, you will have to give up a bit of genericity and create a type trait specific for foo
:
#include <type_traits>
template<typename T>
struct foo {};
template<typename T>
struct is_instantiation_of_foo : std::false_type { };
template<typename...Ts>
struct is_instantiation_of_foo<foo<Ts...>> : std::true_type { };
Which you could then use this way:
template<typename FooType>
struct bar {
static_assert(is_instantiation_of_foo<FooType>::value, ""); //fail
};
Now, none of the assertions in the following program will fire:
template<typename T>
using foo_alt = foo<T>;
int main(int,char**) {
// None of these fail:
bar<foo<int>> b;
bar<foo_alt<int>> b2;
return 0;
}
Here is a live example.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…