鉴于这些定义
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;
这是什么时候发生的,除了将类型设为公开之外还有其他解决方法吗?
答案 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 的名称应该是可访问的 它被用作模板参数。