【问题标题】:boost::variant as friend classboost::variant 作为朋友类
【发布时间】:2015-04-02 09:39:25
【问题描述】:

对于我想在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++ boost c++98 boost-variant


    【解决方案1】:

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

    boost::variant的模板参数个数由BOOST_VARIANT_LIMIT_TYPES给出。你可以通过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 模板参数的类模板,因此您必须这样引用它。这是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 提供了一种替代方法,可以使用和不使用可变参数;详情请见this answer。

    【讨论】:

    • 我认为这不能保证实例化代码是boost::variant 本身,而不是它的帮助类之一。但我没有看过实现。也许它是文档化界面的一部分。
    • @Cheersandhth.-Alf 好点。我回答了“如何与 boost::variant 成为朋友”的问题,而不是更广泛的“如何使用私人 ctor 和 boost::variant”。我将把它留给 OP 来确定它是否适用于他们;我愿意被更好的答案所击败,和/或在发现答案不足的情况下撤回我的答案。
    • 我在 :) 之前检查了 boost::variant 是否进行了实例化。也就是说,该提案至少在 VS2010 上的标识符 BOOST_PP_REPEAT_1_class 中产生了语法错误。
    • @abergmeier 哎呀,我不小心交换了参数顺序。已更正。
    • 我不得不改用template &lt;BOOST_VARIANT_ENUM_PARAMS(class T)&gt; friend class boost::variant;。否则我有一个关于“BOOST_PP_REPEAT_1_BOOST_VARIANT_LIMIT_TYPES”的错误没有被声明
    【解决方案2】:

    当可变参数模板可用时,您必须使用template &lt;BOOST_VARIANT_ENUM_PARAMS(class T)&gt; 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;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-12-31
      • 1970-01-01
      • 2012-12-04
      • 2011-08-10
      • 2010-09-19
      • 1970-01-01
      • 1970-01-01
      • 2011-03-23
      • 1970-01-01
      相关资源
      最近更新 更多