在模板参数中定义类,为什么它无效
Defining a class in a template argument, why is it invalid?
假设代码:
template <class T>
class X { };
int main(void) {
X<class {
int a;
}> x;
return 0;
}
g++5.1给出以下错误消息:
prog.cpp: In function 'int main()':
prog.cpp:5:10: error: types may not be defined in template arguments
X<class {
^
prog.cpp:7:2: error: expected ';' after class definition
}> x;
^
prog.cpp:7:2: error: expected template-argument before ';' token
prog.cpp:7:2: error: expected '>' before ';' token
prog.cpp:7:2: error: 'main()::<anonymous class>' is/uses anonymous type
prog.cpp:7:2: error: trying to instantiate 'template<class T> class X'
prog.cpp:7:2: error: expected '::' before ';' token
prog.cpp:7:2: error: expected identifier before ';' token
prog.cpp:7:3: error: expected primary-expression before '>' token
}> x;
^
prog.cpp:7:5: error: 'x' was not declared in this scope
}> x;
^
错误输出的第二行指出,我们不能在模板参数中定义类型。为什么它无效?(我的意思是,我知道它在标准中是无效的,但原因是什么?)
C++03标准的§14.3.1/2规定:
本地类型、没有链接的类型、未命名的类型或类型由这些类型中的任何一种混合而成的模板类型参数的模板参数。
这基本上意味着你不能做你试图做的事情——使用一个未命名的类型作为模板参数。
我很确定C++11和C++14标准没有修改这段话,但可以随意验证。
更新:C++11确实取消了本地类型限制-现在模板参数允许这样做,但匿名类型不允许:https://stackoverflow.com/a/4573104/634821
没有充分的理由允许它,尽管我不确定是否有强烈的技术原因造成限制。在C++98中,对可以用作模板参数的类型添加了限制,这些类型可能比需要的更强,部分原因是担心未知(我们如何处理对没有名称的类型的篡改?)。
C++11为该语言添加了Lambda,它可以在模板中使用。Lambdas是局部类型,因此对局部类型的限制已经取消。但它们并不是未命名的,它们的名称只是由编译器生成的未命名的。
生成这些名称并将其用于篡改的相同技术可能在您的特定情况下可用,尽管它们可能不适用于所有未命名的类型——编译器使用函数名等信息生成lambda名称,由于ODR,函数名保证允许唯一的名称。在一般情况下,可以在命名空间级别创建未命名的类型,在命名空间级别更难确定对类型进行篡改的正确方式。
行中有几个错误:
X<class {
int a;
}> x;
- 你试图在一个不合法的地方定义一个类
- 您没有为实例化
X
提供类型名 - 您正试图使用未命名的类来实例化
X
最简单的修复方法是使用:
struct A { int a; };
X<A> x;
如果您能够使用C++11编译器。如果您没有访问C++11编译器的权限,则需要将struct A
的定义移动到main
之外。
更新,以回应OP的意见
允许您建议的语法涉及到定义类的语法的重大更改。目前,您需要一个语句来定义一个类,甚至是一个未命名的类。
struct A { ... } ;
// ^^ Need this to define a class/struct
struct { ... } obj ;
// ^^ Need this to define an unnamed class/struct too.
使用您的代码
X<class {int a} > x;
// ^^ There is no scope for a statement.
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- 为什么我收到"从常量指针到指针的转换无效?
- 为什么在引用指针时将 const 放在 & 符号的左侧有效,而在右侧则无效?
- 为什么通过 vector<reference_wrapper> 的元素删除引用的值<T>不会使向量无效?
- 在基数排序中,我得到 munmap_chunk():无效指针和中止(核心转储).为什么?
- 为什么这种向量声明无效?
- 为什么这个正则表达式C++在括号表达式中抛出无效范围异常?
- 为什么 CRTP 模板C++给出无效参数错误?
- 使用 CMake 与其他静态库链接的静态库 - 一个有效,一个无效。为什么?
- 为什么我总是收到此错误:从类型为"农场动物"的右值初始化类型的非常量引用无效|
- 为什么右值不能绑定到非常量左值引用,除了写入临时无效的事实?
- 为什么构造函数的虚拟函数调用有时有效,但其他调用却无效
- 为什么此字符串在传递到stoi时被视为无效参数
- 我得到了一个没有被忽略的无效值,因为它应该是错误的,为什么
- 为什么 std::d eclval<int>() = std::d eclval<int>() 无效?
- 为什么我得到 munmap_chunk():无效的指针:错误
- 无法确定为什么函数调用中从 char* 到 char 的无效转换
- 为什么第二个代码有效而第一个代码无效?
- 为什么我收到此错误:constexpr' 在这里无效
- 为什么无效指针与参考值不同