奇怪的建议模板参数转换

strange suggested template parameter conversion

本文关键字:参数 转换      更新时间:2023-10-16

在《C++模板 - 完整指南》一书中,Vandevoorde & Josuttis建议使用以下片段来确定类型是否是类。参数是:"对于类类型,我们可以依靠观察,即指向成员类型构造 int C::* 的指针仅在 C 是类类型时才有效"作为决定类型是否为"类"类型的策略。

我有两个问题:

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 无关。这是沼泽标准的原始配方SFINAE:您正在检查int C::*的良好成型性。

在我们开始之前,你把它括起来是错误的。您希望将sizeof应用于test的结果,而不是==

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

(另外,摆脱void main()

现在,MSVC 2013 由于某种原因尝试执行推导,并在执行限定调用时忽略指定的模板参数:

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

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

无论如何,您都不需要合格的呼叫。只需写test<T>(0)并执行不合格的调用:

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

它适用于我的 MSVC 2013。