gpt4 book ai didi

c++ - 需要前向声明的嵌套类中的友元声明

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:08:43 25 4
gpt4 key购买 nike

我正在尝试为具有私有(private)成员的嵌套类编写非侵入式 boost::serialization 例程。不幸的是,我没能说服 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_ 是私有(private)的,即使存在友元声明也是如此。 g++ 拒绝内部类中的友元声明是否正确?

最佳答案

[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; [...].

换句话说,具有限定名称的声明(包括友元声明)必须引用先前声明的内容。所以 GCC 在拒绝代码方面是正确的,但它应该更早地拒绝它,并且诊断相当困惑。 (请注意,如果成为 friend 的东西是以前未声明的普通函数而不是模板,它将当场拒绝。)

此外,要求好友访问权从一开始就违背了非侵入式序列化的要点(即允许您在不更改类定义的情况下对其进行序列化)。

关于c++ - 需要前向声明的嵌套类中的友元声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34318661/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com