我从Nicolai M. Josuttis的“C ++模板 - 完整指南”中尝试了这个例子
#include <iostream>
using namespace std;
template< typename T >
class List {
};
typedef enum { RED, GREEN, BLUE } *color_ptr;
int main() {
struct Local {
int x;
};
List< Local > l; // error : local type in template argument
List< color_ptr > l1; // error : unamed type in template argument.
return 0;
}
使用Ubuntu 9.04下的g ++,我遇到了编译器错误。但是,这段代码在Visual C ++ 2008中成功编译。正如我从书中读到的那样: “模板类型参数是为模板类型参数指定的”值“。最常用的类型可以用作模板参数,但有两个例外: 1.本地类和枚举(换句话说,在函数定义中声明的类型)不能涉及模板类型参数。 2.涉及未命名的类类型或未命名的枚举类型的类型不能是模板类型参数(通过typedef声明给出名称的未命名类或枚举都可以。) 那么Visual C ++中是否存在错误?
答案 0 :(得分:3)
在许多其他情况下,您发现该书与VC ++的行为不同。示例是typename
和template
歧义工具以及非常量引用与rvalues的绑定。
在这种情况下,正如书中所说,当然G ++的行为是正确的。请尝试以下更改
typedef enum color_type { RED, GREEN, BLUE } *color_ptr;
template< typename T >
class List {
};
// not really local anymore :)
struct Local { int x; };
int main() {
List< Local > l;
List< color_type > l1;
}
下一个C ++标准(C ++ 0x)允许本地类型作为模板参数。
请注意本书为使用typedef的类型命名的含义。这不适用于以下内容,因为名称A
未命名枚举类型,而是指向它的指针类型。
typedef enum { X } *A;
因此,当您使用A
或您的示例color_ptr
时,您就不安全了。从技术上讲,该名称是指向没有链接的类型的指针类型,不允许作为模板参数。
请注意,您可以将Local
放入未命名的命名空间,以使该类型为当前转换单元的本地类型,但仍具有可接受的类型作为类型模板参数。这样,如果你只想为函数对象之类的东西设置一个“scratch”类型,那么struct不会与另一个文件中定义的struct冲突。
namespace {
// not really local anymore, but "translation unit local" :)
struct Local { int x; };
}
答案 1 :(得分:1)
这些是MSVC标准的允许扩展。 MS在记录编译器的options,符合或偏离标准方面做得不错,并且c;特别是,如记录here,/Za
将告诉编译器标记为与标准的错误偏差(它特别称为“ansi C ++”而不是ISO; - )。
答案 2 :(得分:0)
检查您是否正在使用Microsoft扩展(/ Ze)进行编译。