我在成员函数(构造函数)Foo中定义了一个类Bar,我试图将其用作模板参数。
template<typename Ty>
struct Spam {
template<class U, class D> Spam(U*, D) {}
};
struct Foo {
Foo() {
struct Bar {};
int *ptr = NULL;
Spam<int> pSpam(ptr, Bar());
}
};
我的猜测是用法无效,因为Bar的范围是Foo的本地范围,并且不能具有模板实例化所需的全局可见性。但是在第二种情况下,我在Bar的相同范围内实例化模板,虽然模板类/结构是全局的,但模板实例不应存在任何可访问性问题。
我尝试了多个编译器,每个编译器的行为都不同。特别是
clang接受警告
warning: template argument uses local type 'Bar' [-Wlocal-type-template-args]
VC ++编译时没有警告
GCC 4.3.4编译失败
10 : error: no matching function for call to 'Spam::Spam(int*&, Foo::Foo()::Bar)'
3 : note: candidates are: Spam::Spam(const Spam&)
GCC C ++ 14编译成功
根据标准,预期的行为是什么?
答案 0 :(得分:3)
C ++ 2003标准14.3.1 / 2指定
本地类型,没有链接的类型,未命名的类型或类型 任何这些类型的复合不得用作 模板类型参数的模板参数。
template <class T> class X { /* ... */ };
void f()
{
struct S { /* ... */ };
X<S> x3; // error: local type used as template-argument
X<S*> x4; // error: pointer to local type used as template-argument
}
但是在C ++ 11及更高版本中允许它。
N3797 14.3.1 / 2
template <class T> class X { };
template <class T> void f(T t) { }
struct { } unnamed_obj;
void f()
{
struct A { };
enum { e1 };
typedef struct { } B;
B b;
X<A> x1; // OK
X<A*> x2; // OK
X<B> x3; // OK
f(e1); // OK
f(unnamed_obj); // OK
f(b); // OK
}