奇怪的建议模板参数转换

strange suggested template parameter conversion

在 C++ 模板 - 完整指南,Vandevoorde 和 Josuttis 一书中,建议使用以下代码段来确定类型是否为 class。论点是:"For class types we can rely on the observation that the pointer to member type construct int C::* is valid only if C is a class type" 作为决定类型是否为 "class" 类型的策略。

我有两个问题:

1) 你认为这个论点成立吗? 2) 你将如何修改(保留策略)下面的代码片段以使其工作,因为它不能在 MSVC2013 上编译?

using namespace std;

template<typename T>
class IsClass
{
    typedef char One;
    typedef struct 
    { 
        char a[2];
    } Two;
    template<typename C> static One test(int C::*);
    template<typename C> static Two test(...);
public:
    enum { YES = (sizeof(IsClass<T>::test<T>(0) == 1)) };
};

class C{};

void main()
{
    if (IsClass<C>::YES)
        std::cout << "C Is a Class" << endl;
}

与评论相反,您的问题与表达式 SFINAE 无关。这是 bog-standard original-recipe SFINAE:您正在检查 类型 int C::*.

的 well-formedness

在我们开始之前,你括号错了。您想要将 sizeof 应用到 test 的结果,而不是 ==:

enum { YES = (sizeof(IsClass<T>::test<T>(0)) == 1) };
             //     ^                      ^

(另外,get rid of void main()。)

现在,MSVC 2013 出于某种原因尝试进行推导并忽略指定的模板参数,如果您进行合格的调用:

    IsClass<T>::test<T>(0)
//  ^^^^^^^^^^^^

这显然是一个错误。我不确定它为什么会这样,但是 MSVC 前端的大部分都是用胶带固定在一起的,所以我并不感到惊讶。

反正你不需要合格的电话。直接写test<T>(0),做一个不合格的调用:

enum { YES = (sizeof(test<T>(0)) == 1) };

适用于我的 MSVC 2013。