c++ std::enable_if_t与部分专用化不匹配

6pp0gazn  于 2023-02-20  发布在  其他
关注(0)|答案(2)|浏览(132)

如果我的理解是正确的,别名模板实际上是模板,因此可以作为参数传递到类模板所在的位置,这就是下面代码有效的原因-

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的情况下,第二个部分特化不是应该更好吗?

3df52oht

3df52oht1#

正如预期的那样,下面将打印“版本2”

foo<std::enable_if<true, int>>::print();

但是,在您的示例中,类型std::enable_if_t<true, int>等效于int,不能匹配不能匹配T<X, Y>
cppreference对此进行了解释like this
别名模板是这样一种模板,在专用化时,它等效于用别名模板的模板参数替换 type-id 中的模板参数的结果
别名std::enable_if_t可以匹配template <bool, typename> typename,但是一旦被专门化,就不能被解构。

y4ekin9u

y4ekin9u2#

只要别名模板有参数,它就会立即替换为它的别名类型。例如,std::enable_if_t<true, int>立即替换为int。这甚至适用于依赖上下文;例如,如果你有这样一个函数:

template <bool b, typename T>
void foo(std::enable_if_t<b, T>);

编译器将其重写为:

template <bool b, typename T>
void foo(typename std::enable_if<b, T>::type);

原来的别名已经从等式中消失了。
由此得出结论,诸如T<X, Y>的类型不能用于将T推导为别名模板,因为无论为T<X, Y>提供什么类型U来进行匹配,如果对于某个别名模板A,它最初具有A<X, Y>的形式,则它将被该别名模板别名为的任何类型所替换,并且A将不再存在。(然而,别名模板可以被推导为具有模板template参数的类模板的 argument,因为别名模板可以是有效的模板template参数)

相关问题