什么时候可以在私有成员类型上专门化模板?

时间:2015-06-24 17:21:54

标签: c++ templates

鉴于这些定义

template<class T> class foo {};
template<class T> class foo1 { static int i; };
class bar { class baz {}; };

我很惊讶地看到这个编译

template<>
class foo<bar::baz> {};

但是失败并显示错误'class bar::baz' is private

template<>
int foo1<bar::baz>::i = 42;

这是什么时候发生的,除了将类型设为公开之外还有其他解决方法吗?

1 个答案:

答案 0 :(得分:5)

考虑CWG #182

  

在显式实例化时禁止某些访问检查。   14.7.2 [temp.explicit]第8段说[...]我很惊讶类似的措辞不存在(我能找到)用于显式   专业化。我认为应该处理这两个案件   等效于下面的例子(即专业化   应该被允许)。

template <class T> struct C {
  void f();
  void g();
};

template <class T> void C<T>::f(){}
template <class T> void C<T>::g(){}

class A {
  class B {};
  void f();
};

template void C<A::B>::f();    // okay
template <> void C<A::B>::g(); // error - A::B inaccessible
     

[...]

     

理由(2002年10月)

     

我们重新考虑了这一点并决定了两者之间的区别   案例(显式专业化和显式实例化)是   适当。访问规则有时会在必要时弯曲   允许命名某些内容,如在显式实例化中,但显式   专业化不仅需要命名实体,还需要提供   某处的定义。

GCC和Clang确实拒绝了所示示例的最后一行,这显然是 - 不一致的行为,对于类模板的相应显式特化,它们不会发出错误消息:

template <class> struct T {
    void g();
};

class A { class B; class C; };

template <> struct T<A::B>;    // Ok
template <> void T<A::C>::g(); // Error

Demo。因此,我会在这里发出一个问题并将你所展示的两个案例称为§14.3/ 3:

  

template-argument 的名称应该是可访问的   它被用作模板参数