10

以下代码

#include <iostream>
#include <utility>

template<typename F, typename... T>
struct Wrapper{ };

template<typename T>
struct is_wrapper : std::false_type {};

template<typename... T>
struct is_wrapper<Wrapper<T...>> : std::true_type {};

//template<typename F, typename... T>
//struct is_wrapper<Wrapper<F, T...>> : std::true_type {};

int main()
{
    Wrapper<int, double> w;

    std::cout << is_wrapper<decltype(w)>::value << std::endl;
}

打印 0。但是,如果取消注释中间的两行,它会打印 1。

为什么它不总是打印 1?第二部分专业化不应该也涵盖显然仅由第三(评论)部分专业化涵盖的情况吗?

4

3 回答 3

1

代码确实应该匹配偏特化;该标准实际上从未不允许这样做,但编译器确实需要一段时间来正确实现可变参数模板及其推导。GCC 自 4.9.0 起符合,Clang 自 3.6 起符合。Clang 的相关错误报告是#22191(不过我找不到 GCC)。

于 2015-08-10T12:23:02.630 回答
0

如果我能很好地理解您的问题,那只是专业化优先级,

is_wrapper<decltype(w)>

可以通过2个模板专门化:

template<typename T> // exact specialization
template<typename... T> // variadic specialization with one parameter 

在这种情况下,编译器优先选择确切的专业化,因此在您的情况下模板永远不会实例化。

于 2014-05-31T08:09:01.540 回答
0

通常,当我编写专门化的模板时,我首先使用前向声明,并声明这些案例属于专门化。在您的情况下,我了解您正在尝试编写一个没有空大小写的可变参数模板(也就是说,一个可变参数模板至少可以有一种类型)。

您的代码让我感到惊讶,因为我认为您是正确的,您的 trait 的完整可变参数特化与空洞情况相匹配...首先我尝试使用您的 trait 类的前向声明,并仅定义完整可变参数特化(因此,如果特征的参数不是Wrapper编译失败的实例)。这正是发生的事情,再次让我失望:

#include <iostream>
#include <utility>

template<typename F , typename... T>
struct Wrapper {};

template<typename T>
struct is_wrapper;

//template<typename T>
//struct is_wrapper : std::false_type {};

template<typename... T>
struct is_wrapper<Wrapper<T...>> : std::true_type {};

//template<typename F, typename... T>
//struct is_wrapper<Wrapper<F, T...>> : std::true_type {};

using my_wrapper_type = Wrapper<int,double>;

int main()
{   
    std::cout << std::boolalpha  << is_wrapper<my_wrapper_type>::value << std::endl;
}//"Invalid use of incomplete type" ^^^^^^^^^^^^^^^^^^^^^^^^^^^

最后我尝试了Wrapper类中的前向声明方法。令人惊讶的是,它有效:

#include <iostream>
#include <utility>

template<typename... T>
struct Wrapper;

template<typename F, typename... T>
struct Wrapper<F,T...>{ };


template<typename T>
struct is_wrapper : std::false_type {};

template<typename... T>
struct is_wrapper<Wrapper<T...>> : std::true_type {};

//template<typename F, typename... T>
//struct is_wrapper<Wrapper<F, T...>> : std::true_type {};


using my_wrapper_type = Wrapper<int,double>;

int main()
{
    std::cout << std::boolalpha  << is_wrapper<my_wrapper_type>::value << std::endl;
}

这打印:

真的

是在 ideone 运行的代码。

真诚地,我不明白为什么您的代码失败而我的代码有效。它是一个编译器错误,还是我们缺少什么?我不知道。

于 2013-08-11T15:07:22.790 回答