作为友元的封闭命名空间中的模板类
template class in enclosing namespace as friend
我的代码具有以下基本结构
namespace my {
template<typename> class A; // forward declaration
namespace details {
template<typename T> class B
{
const T*const t;
B(const T*x) : t(x) {} // non-public constructor
template<typename> friend class A; // friend declaration
};
}
template<typename T> class A
{
T*const t;
public:
A(T*x) : t(x) {}
details::B<T> makeb() const // offending method:
{ return details::B<T>(t); } // calls non-public constructor
};
}
在GCC (4.7 &4.8,使用-std=c++11
)和icpc(13.1),但没有clang(使用-std=c++11 -stdlib=libc++
),它抱怨使用非公共构造函数(当实例化违规方法时)。如果友元声明给出完整的限定名,如
template<typename> friend class my::A;
这是clang的bug吗?我本以为封闭命名空间my
中的任何可见符号都可以使用,而无需在内部命名空间my::details
中进一步限定。2011年的标准是怎么说的?
我认为Clang是对的:
7.3.1.2命名空间成员定义[namspace .memdef]3在命名空间中首先声明的每个名称都是该命名空间的成员。如果非局部类中的
friend
声明首先声明了一个类、函数、类模板或函数模板,则友元是最内层封闭命名空间的成员。非限定查找(3.4.1)或限定查找(3.4.3)不会找到友元的名称,直到在该命名空间作用域中提供了匹配声明(在授予友元的类定义之前或之后)。如果调用友元函数或函数模板,则可以通过名称查找来查找其名称,该查找考虑与函数实参类型相关的命名空间和类中的函数(3.4.2)。如果friend
声明中的名称既不是限定的,也不是模板id,并且声明是函数或详细类型说明符,则查找确定实体是否先前声明过,不应考虑最内层封闭命名空间之外的任何作用域。[注意:其他形式的友元声明不能声明最内层封闭命名空间的新成员,因此不能遵循通常的查找规则。- 结束说明] [示例:
// Assume f and g have not yet been declared.
void h(int);
template <class T> void f2(T);
namespace A {
class X {
friend void f(X); // A::f(X) is a friend
class Y {
friend void g(); // A::g is a friend
friend void h(int); // A::h is a friend
// ::h not considered
friend void f2<>(int); // ::f2<>(int) is a friend
};
};
// A::f, A::g and A::h are not visible here
X x;
void g() { f(x); } // definition of A::g
void f(X) { /* ... */} // definition of A::f
void h(int) { /* ... */ } // definition of A::h
// A::f, A::g and A::h are visible here and known to be friends
}
using A::x;
void h() {
A::f(x);
A::X::f(x); // error: f is not a member of A::X
A::X::Y::g(); // error: g is not a member of A::X::Y
}
- 结束示例]
注意// ::h not considered
相关文章:
- C++ 17 个友元函数声明和内联命名空间
- 为什么 gcc 无法从其前向声明中检测到友元类命名空间?
- c++ 内联友元函数是否会导致命名空间之间的名称隐藏?
- 友元类指向不同命名空间中同名的类
- 跨命名空间的友元类和不同的.H 文件
- 在 c++ 中定义命名空间中模板类的友元函数时出现问题
- 匿名命名空间中模板化类的友元
- 另一个命名空间和 CRTP 中的模板友元函数
- 类内定义的友元函数的调试标志中的命名空间
- 关于友元函数定义和命名空间范围
- 将命名空间声明为类的友元
- 模板对象的模板友元函数和命名空间
- Qt 命名空间的元类型信息
- 命名空间内类的友元函数
- 为什么我的类友元函数无法访问具有命名空间的受保护成员?
- 命名空间内出现错误 C2248 友元类
- 如何在gtest中使用带有命名空间的友元类
- 哪个命名空间确实包含此友元函数的声明
- 不同命名空间中的友元运算符
- 命名空间内的友元函数声明/定义