在模板参数中定义类,为什么它无效

Defining a class in a template argument, why is it invalid?

本文关键字:为什么 无效 定义 参数      更新时间:2023-10-16

假设代码:

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;
  1. 你试图在一个不合法的地方定义一个类
  2. 您没有为实例化X提供类型名
  3. 您正试图使用未命名的类来实例化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.         
相关文章: