需要前向声明的嵌套类中的朋友声明(Friend declaration in nested classes requiring forward declaration)

系统教程 行业动态 更新时间:2024-06-14 16:57:18
需要前向声明的嵌套类中的朋友声明(Friend declaration in nested classes requiring forward declaration)

我正在尝试使用私有成员为嵌套类编写非侵入式boost ::序列化例程。 不幸的是,我没有说服g ++,序列化例程是内部类的朋友。 看来g ++需要序列化例程的前向声明,而这又需要一个嵌套类的前向声明,而这又不能用C ++来完成。 我错过了什么,或者这仅仅是不可能的? 铿锵++相比,不需要前向声明,并且与下面的代码没有问题。 以下代码说明了这个问题:

#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 ++是否拒绝内部类中的朋友声明?

I am trying to write non-intrusive boost::serialization routines for a nested class with a private member. Unfortunately, I fail to convince g++ that the serialization routine is a friend of the inner class. It seems g++ requires a forward declaration of the serialization routine, which in turn would need a forward declaration of the nested class, which in turn cannot be done in C++. Am I missing something or is this just not possible? clang++ in contrast does not need a forward declaration and has no problems with the code below. The following code illustrates the problem:

#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; }

To be compiled with -std=c++11 and -lboost_serialization. Compilation with g++ complains that member_ is private even though a friend declaration is present. Is g++ right in refusing the friend declaration in the inner class?

最满意答案

[dcl.meaning] / 1 :

declarator-id被限定时,声明应引用预先定义的限定符所引用的类或名称空间的成员 (或者在名称空间的情况下,该名称空间的内联名字空间集的一个元素([ namespace.def]))或其专业化; [...]。

换句话说,具有限定名称的声明(包括朋友声明)必须引用先前声明的内容。 所以GCC在拒绝代码方面是正确的,但它应该在早期拒绝它,并且诊断相当混乱。 (请注意,如果被贿赂的对象是以前未声明的普通函数而不是模板,则它会在现场拒绝。)

此外,要求朋友访问类首先击败了非侵入式序列化的位置(这是为了让您序列化一个类而不更改其定义)。

[dcl.meaning]/1:

When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers (or, in the case of a namespace, of an element of the inline namespace set of that namespace ([namespace.def])) or to a specialization thereof; [...].

In other words, a declaration (including a friend declaration) with a qualified name must refer to something previously declared. So GCC is sort of correct in rejecting the code, but it should have rejected it earlier, and the diagnostic is rather confusing. (Note that it will reject it on the spot if the thing being friended is a previously-undeclared plain function and not a template.)

Also, requiring friend access sort of defeats the point of non-intrusive serialization in the first place (which is to allow you to serialize a class without changing its definition).

更多推荐

本文发布于:2023-04-12 20:38:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/dzcp/7405e3ab0aa24f79bea6a2f2977dae90.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:声明   嵌套   前向   类中   朋友

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!