在允许用作模板类型的函数内使用内联类?

时间:2015-09-01 07:59:05

标签: c++ templates nested-class

我在成员函数(构造函数)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编译成功

根据标准,预期的行为是什么?

1 个答案:

答案 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
}