boost::variant 作为朋友 class

boost::variant as friend class

对于我想在 boost::variant 中使用的类型 Foo,我想将默认构造函数设置为 private,因为只允许调用它通过 boost::variant.

可悲的是我还没有弄清楚 boost::variant 的声明魔法并简单地声明

struct Foo {
private:
  Foo();
  template <class T1, class T2>
  friend class boost::variant<T1, T2>;
};

也没编译通过。有什么办法可以做到这一点,还是我需要保留 Foo() public?

[此答案仅针对 C++98/03;对于现代代码,见下文]

boost::variant的模板参数个数由BOOST_VARIANT_LIMIT_TYPES. You could use it by harnessing Boost.Preprocessor给出:

#include "boost/preprocessor/repetition/enum_params.hpp"

struct Foo {
private:
  Foo();

  template <BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, class T)>
  friend class boost::variant;
};

boost::variant 声明为带有 BOOST_VARIANT_LIMIT_TYPES 模板参数的 class 模板,因此您必须这样引用它。这是 BOOST_PP_ENUM_PARAMS(a, b) 的工作,它扩展为 a 逗号分隔项目的列表,每个项目都是 b 附加的唯一编号。例如,

BOOST_PP_ENUM_PARAMS(5, class T)

将扩展为:

class T0, class T1, class T2, class T3, class T4

注意,以上适用于题目范围内,即仅限于C++98/03。自 C++11 起,存在可变参数模板,当这些模板可用于 Boost 时,BOOST_VARIANT_LIMIT_TYPES 未定义且上述代码不起作用。 Boost 提供了一种替代方案,它可以使用和不使用可变参数;有关详细信息,请参阅

当可变参数模板可用时,您必须使用 template <BOOST_VARIANT_ENUM_PARAMS(class T)> friend class boost::variant; 否则会出现错误:“BOOST_PP_REPEAT_1_BOOST_VARIANT_LIMIT_TYPES”尚未声明。

这是最小的 working example:

#include <boost/variant.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>

struct Foo {
public:
    Foo(int){};
private:
    Foo();
    template <BOOST_VARIANT_ENUM_PARAMS(class T)> friend class boost::variant;
    int i;
};

int main()
{
    Foo foo(10);
    boost::variant<Foo> test=foo;
}