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

时间:2016-01-09 22:16:02

标签: c++

假设代码:

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;
     ^

错误输出的第二行表示我们无法在模板参数中定义类型。为什么无效? (我的意思是,我知道它在标准中无效,但原因是什么?)

3 个答案:

答案 0 :(得分:4)

来自C ++ 03标准的§14.3.1/ 2表示:

  

本地类型,没有链接的类型,未命名的类型或类型   任何这些类型的复合不得用作   模板类型参数的模板参数。

这基本上意味着你无法做你想做的事情 - 使用未命名的类型作为模板参数。

我很确定C ++ 11和C ++ 14标准没有修改该段落,但可以随意验证。

更新:C ++ 11确实取消了本地类型限制 - 现在允许模板参数,但不允许匿名类型:https://stackoverflow.com/a/4573104/634821

答案 1 :(得分:1)

没有充分的理由允许它,虽然我不确定是否存在这种限制的强大技术原因。在C ++ 98中,对可以用作模板参数的类型添加了限制,这些类型可能比所需更强,部分原因是由于害怕未知(我们如何处理没有名称的类型的修改?)。

C ++ 11在语言中添加了lambda,可以在模板中使用。 Lambdas是本地类型,因此对局部类型的限制已被取消。但它们不是未命名,它们的名称只是不可记录并由编译器生成。

生成这些名称并将它们用于修改的相同技术可能在您的特定情况下可用,尽管它们可能不适用于所有未命名类型 - 编译器使用函数名称生成lambda名称,这是由于ODR保证允许使用唯一的名称。在一般情况下,可以在命名空间级别创建未命名的类型,在那里确定修改类型的正确方法会更难。

答案 2 :(得分:0)

行中有几个错误:

X<class {
    int a;
}> x;
  1. 您正试图在不合法的地方定义课程。
  2. 您没有提供类型名称来实例化X
  3. 您正在尝试使用未命名的类来实例化X
  4. 最简单的解决方法是使用:

    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.