【问题标题】:Determining whether a type is a class type?判断一个类型是否是类类型?
【发布时间】:2018-06-21 18:41:12
【问题描述】:

在“C++ 模板 - 完整指南 - 第二版”一书的第 19.8.4 章中,作者展示了如何在编译时确定一个类型是否是类类型:

#include <iostream>
#include <type_traits>
using namespace std;

template <typename T, typename = void_t<>>
struct IsClass : false_type { };

template <typename T>
struct IsClass<T, void_t<int T::*>> : true_type { };

int main()
{
    struct S { };
    cout << IsClass<S>::value; // prints 1
}

本段解释了偏特化如何检测类类型:

...只有类类型可以用作指向成员类型的基础。也就是说,在X Y::* 形式的类型构造中,Y 只能是类类型。以下IsClass&lt;T&gt; 的公式利用了该属性(并任意选择int 类型X

我不明白的是为什么选择intX 有效,即使我们使用完全没有成员的结构S 测试IsClass&lt;&gt;(它也适用于具有成员的类类型除了int)

【问题讨论】:

  • 类不需要有成员来声明指向成员类型的指针。这类似于没有函数不会阻止声明指向函数类型的指针。

标签: c++ templates sfinae typetraits partial-specialization


【解决方案1】:

简而言之,因为标准是这样说的。

根据[dcl.mptr]/2(我这里只包括相关部分):

[ 例子:

struct X {
  int a;
};
struct Y;

double X::* pmd;
char Y::* pmc;

。 . .
即使X 没有double 类型的成员,pmd 的声明也是格式良好的。同样,pmc 的声明格式良好,即使 Y 是不完整的类型。
. . .

基本上,只要已知类型 S 属于类类型,那么构造 S::* 就是格式良好的。

所以你甚至可以拥有这个:

int main()
{
    struct S;
    cout << IsClass<S>::value; // still prints 1
}

【讨论】:

    【解决方案2】:

    我不明白的是为什么选择 intX 有效,即使我们使用完全没有成员的结构 S 测试 IsClass(它也适用于具有非 int 成员的类类型)

    它不一定是int,因为它只是作为一个占位符。 您可以将其替换为 doublechar 并看到相同的结果。

    给定的类类型T 是否有成员函数根本不重要,因为IsClass 试图看到的只是那个表达式:

    X Y::*
    

    格式正确

    这就像你不需要一个实际的函数定义(非成员函数)仅仅声明一个指向该函数的指针类型如下:

    int main()
    {
        // It doesn't matter whether there's a function int (*)(int, int, int) indeed because it's just merely a declaration
        using FuncP = int (*)(int, int, int);
        FuncP P;
    }
    

    【讨论】:

      猜你喜欢
      • 2012-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-17
      • 1970-01-01
      • 2019-09-14
      • 1970-01-01
      • 2014-09-17
      相关资源
      最近更新 更多