如果我的理解是正确的,别名模板实际上是模板,因此可以作为参数传递到类模板所在的位置,这就是下面代码有效的原因-
template <template <bool, typename> T>
struct foo {};
foo<std::enable_if_t> x;
也可以使用部分专门化来匹配模板类。这就是为什么下面的代码打印“版本2”。
template <typename T>
struct foo {
static void print() {std::cout << "Version 1" << std::endl;}
};
template <template <typename> typename T, typename X>
struct foo<T<X>> {
static void print() {std::cout << "Version 2" << std::endl;}
};
template <typename T>
struct bar {
};
...
foo<bar<int>>::print();
现在我的问题是,为什么下面的代码不打印“版本2,”而是打印“版本1”
template <typename T>
struct foo {
static void print() {std::cout << "Version 1" << std::endl;}
};
template <template <bool, typename> typename T, bool X, typename Y>
struct foo<T<X, Y>> {
static void print() {std::cout << "Version 2" << std::endl;}
};
foo<std::enable_if_t<true, int>>::print();
在T=std::enable_if_t,X=true,Y=int的情况下,第二个部分特化不是应该更好吗?
2条答案
按热度按时间3df52oht1#
正如预期的那样,下面将打印“版本2”
但是,在您的示例中,类型
std::enable_if_t<true, int>
等效于int
,不能匹配不能匹配T<X, Y>
。cppreference对此进行了解释like this:
别名模板是这样一种模板,在专用化时,它等效于用别名模板的模板参数替换 type-id 中的模板参数的结果
别名
std::enable_if_t
可以匹配template <bool, typename> typename
,但是一旦被专门化,就不能被解构。y4ekin9u2#
只要别名模板有参数,它就会立即替换为它的别名类型。例如,
std::enable_if_t<true, int>
立即替换为int
。这甚至适用于依赖上下文;例如,如果你有这样一个函数:编译器将其重写为:
原来的别名已经从等式中消失了。
由此得出结论,诸如
T<X, Y>
的类型不能用于将T
推导为别名模板,因为无论为T<X, Y>
提供什么类型U
来进行匹配,如果对于某个别名模板A
,它最初具有A<X, Y>
的形式,则它将被该别名模板别名为的任何类型所替换,并且A
将不再存在。(然而,别名模板可以被推导为具有模板template参数的类模板的 argument,因为别名模板可以是有效的模板template参数)