gpt4 book ai didi

c++ - 抽象类分类的模板语法

转载 作者:太空狗 更新时间:2023-10-29 20:22:11 25 4
gpt4 key购买 nike

在浏览一些代码时,我遇到了以下模板:

template<typename T>
class is_abstract
{
class No { };
class Yes { No no[3]; };

template<class U>
static No test(U (*)[1]); // not defined

template<class U>
static Yes test(...); // not defined

public:
enum { result = (sizeof(test<T>(0)) == sizeof(Yes)) };
};

我明白 test<T>(0)将通过返回 No 的重载调用对于非抽象 ( is_abstract<SomeAbstractClass>::result = true) 类和其他重载,但为什么呢?

这是什么U (*)[1]方法签名中的语法?

最佳答案

test<T>(0)将调用 test 的第一次或第二次重载.第二个重载非常标准(它是第一个重载格式错误时的回退)。

现在,如何使抽象类的第一个声明格式错误?以下是一些可能的解决方案:

template<class U>
static No test(U); // (1)

template<class U>
static No test(U*); // (2)

template<class U>
static No test(U (*)[1]); // (3)

但是(1) 有问题和 (2) :

  1. 您需要调用 test<T>(T()) ,这对于任何抽象类都是错误的 T (不仅是声明,还有调用),所以SFINAE不会工作(不会有回退,因为代码在重载解析“之前”是格式错误的);
  2. U*总是有效的,即使对于抽象类也是如此,所以这是不行的;
  3. 可能是自 U (*)[1] 以来更简单的解决方案不需要您实例化 T()在调用期间,但抽象类型的声明格式不正确,因此回退到 test(...)根据需要工作。

请注意,从 C++11 开始,有一个 std::is_abstract 标准定义的类。


关于 is_* 的旁注类:

这可能是一个旧的实现,现在有更简单的方法来做到这一点(自 C++11 起)。另请注意,使用 value而不是 result这里会好得多(会遵循标准约定)。遵循标准约定的 C++11 实现可以是1:

template <class T>
std::false_type is_abstract_(T (*)[1]);

template <class T>
std::true_type is_abstract_(...);

template<typename T>
struct is_abstract: decltype(is_abstract_<T>(0)) { };

1 如果你需要测试一个类是否是抽象的,使用标准 std::is_abstract , 但如果您需要创建自己的 is_*类,你应该按照这个例子而不是你找到的那个。

关于c++ - 抽象类分类的模板语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39145949/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com