用于分类抽象类的模板语法
Template syntax for classifying abstract classes
在浏览一些代码时,我遇到了以下模板:
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)
将被重载调用,该重载为非抽象( is_abstract<SomeAbstractClass>::result
= true)类和其他重载调用No
,否则,为什么?
方法签名中的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)
有问题:
- 您需要调用
test<T>(T())
,这对于任何抽象类T
(不仅声明,而且调用)来说都是病态的,因此SFINAE将无法工作(因为代码在"之前"是病态的); -
U*
总是有效的,即使是抽象类,所以这是不可以的; - 可能是这里更简单的解决方案,因为
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_*
类,您应该遵循这个示例,而不是您找到的
U (*)[1]
是一个指向U
实例的数组指针。
由于抽象类不能被实例化,这样的数组将是错误的,因此重载将被忽略(这是SFINAE),并且调用返回到(...)
重载。
相关文章:
- 1d 智能指针不适用于语法 (*)++
- 助记符和指向成员语法的指针
- 有人能分解一下这个c++模板的语法吗
- C++避免重复声明的语法是什么
- QMetaObject invokeMethod的基于函数指针的语法
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 单独定义模板化嵌套类方法的正确语法
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- 为我的 c++ 类介绍制作一个三角形分类器.我有几个问题
- 错误 C2760:语法错误:映射迭代器上意外的标记"标识符",预期的";"
- 为什么我会收到错误 C2143 语法错误:缺少"*"之前的';'?
- 奇怪的代码抛出编译错误模板< J,int aSize=10> C2143:语法错误:在"<"之前缺少";"
- 更改 C++ 中的组合分类变量
- 使用基类指针调用基类的值构造函数的语法是什么?
- 很好的语法来获取对向量/数组数据的大小引用?
- C++语法运算符功能?
- C++使用 rand 定义函数语法
- C++中与模板相关的语法元素的名称分类
- 用于分类抽象类的模板语法