嵌套类中需要前向声明的友元声明
Friend declaration in nested classes requiring forward declaration
我正在尝试为具有私有成员的嵌套类编写非侵入性的boost::序列化例程。不幸的是,我没能让g++相信序列化例程是内部类的朋友。g++似乎需要序列化例程的前向声明,而这反过来又需要嵌套类的前向宣布,而这在C++中是无法实现的。我是错过了什么,还是这不可能?相比之下,clang++不需要前向声明,下面的代码也没有问题。以下代码说明了问题:
#include <boost/archive/text_oarchive.hpp>
class Outer;
//class Outer::Inner; // Not valid C++
namespace boost
{
namespace serialization
{
template <class Archive>
void serialize(Archive &ar, Outer& outer, const unsigned int version);
//template <class Archive>
//void serialize(Archive &ar, Outer::Inner& inner, const unsigned int version); // Cannot be done since forward declaration of nested class not possible.
}
}
class Outer
{
class Inner
{
int member_{42};
template <class Archive>
friend void boost::serialization::serialize(Archive &ar, Outer::Inner &inner, const unsigned int version); // This does not work with gcc since the compiler seems to expect a forward declaration, which cannot be done (see above).
};
Inner inner_;
template <class Archive>
friend void boost::serialization::serialize(Archive &ar, Outer &outer, const unsigned int version);
template <class Archive>
friend void boost::serialization::serialize(Archive &ar, Inner &inner, const unsigned int version);
};
namespace boost
{
namespace serialization
{
template <class Archive>
void serialize(Archive &ar, Outer& outer, const unsigned int version)
{
ar & outer.inner_;
}
template <class Archive>
void serialize(Archive &ar, Outer::Inner& inner, const unsigned int version)
{
ar & inner.member_;
}
}
}
int main()
{
Outer outer;
boost::archive::text_oarchive(std::cout) << outer;
}
用-std=c++11
和-lboost_serialization
编译。使用g++编译抱怨member_
是私有的,即使存在友元声明。g++拒绝内部类中的友元声明是否正确?
[dcl.含义]/1:
当声明符id合格时,声明应参考以前声明的类或命名空间的成员限定符指的是该命名空间的内联命名空间集([namespace.def])或专业化;[…].
换句话说,具有限定名称的声明(包括友元声明)必须引用以前声明的内容。所以GCC拒绝代码是正确的,但它应该更早地拒绝它,而且诊断相当混乱。(注意,如果交友对象是以前未声明的普通函数而不是模板,它会当场拒绝。)
此外,要求友元访问从一开始就有点违背了非侵入性序列化的要点(即允许您在不更改类定义的情况下序列化类)。
相关文章:
- 如何在嵌套类中正确使用友元声明?
- 将子类方法声明为基类的友元
- 在将函数声明为友元时,尖括号的含义是什么?
- 使用typedef'ed返回类型声明友元函数时出现编译器错误
- C++ 17 个友元函数声明和内联命名空间
- 将派生类的构造函数声明为父类的友元
- 为什么 gcc 无法从其前向声明中检测到友元类命名空间?
- 类模板中文本运算符的友元声明
- 以嵌套类为参数的友元模板声明
- 模板和隐式构造函数的类定义之外的友元声明
- 如何将友元声明用于具有约束的模板类
- 为什么我不能定义一元运算符,然后在 MSVC 的模板类中声明具有相同名称的友元二进制运算符?
- 为什么在定义类之前声明类的对象会在友元类中给出错误,而在友元函数中不会出错
- 如何将模板友元函数声明为可变参数类
- 嵌套友元类所需的前向声明
- 在派生类或基类中,我应该在哪里声明友元类
- 类定义交叉引用时如何声明友元方法
- 在此范围内未声明友元函数错误
- GCC声明友元函数是重载的,有歧义调用,clang编译
- 声明友元函数时出现变量作用域错误