代码之家  ›  专栏  ›  技术社区  ›  Nim

基于标志的成员初始化列表中成员的触发器特定构造函数

c++
  •  6
  • Nim  · 技术社区  · 14 年前

    如果我从一个简单的例子开始,这是最简单的:

    #include <boost/optional.hpp>
    #include <boost/none.hpp>
    #include <boost/utility/typed_in_place_factory.hpp>
    
    struct state
    {
      bool flag1;
      bool flag2;
      int value;
    };
    
    class A
    {
    public:
      A() : _a() {}
      A(boost::none_t none) : _a() {}
      A(state& st) : _a(st.value) {}
      A(const A& copy) : _a(copy._a) {}
    
    private:
      boost::optional<int> _a;
    };
    
    class B
    {
    public:
      B() : _b() {}
      B(boost::none_t none) : _b() {}
      B(state& st) : _b(st.value) {}
      B(const B& copy) : _b(copy._b) {}
    
    private:
      boost::optional<int> _b;
    };
    
    class C
    {
    public:
      C() : _a(boost::none_t()), _b(boost::none_t()) {}
      C(state& st) :
        _a(st.flag1 ? st : boost::none_t()),
        _b(st.flag2 ? st : boost::none_t())
      {}
    
    private:
      boost::optional<A> _a;
      boost::optional<B> _b;
    };
    
    int main(void)
    {
      state f = { true, false, 10 };
      C c(f);
    
      return 0;
    }
    

    所以我们的想法是触发 A state ,但是 B 具有 boost::none_t .
    以上代码无法编译,因为三元运算符对这两种可能性都要求相同的类型,并且 boost::无 不是同一类型。 有人能想出一个优雅的方法来解决这个问题吗?

    我知道两种解决方案:

    1. 复制构造,即。

      _a(st.flag1 ? A(st) : A(boost::none_t())), _b(st.flag2 ? B(st) : B(boost::none_t()))

    2. 使用指针而不是 boost::optional<>

      _a(st.flag1 ? new A(st) : new A(boost::none_t())), _b(st.flag2 ? new B(st) : new B(boost::none_t()))

    #2并没有那么吸引人,因为我试图避免动态内存分配(真实的例子有几十个成员和具有更多成员的深度嵌套结构)。
    #1也不吸引人,因为我需要构建然后复制。

    编辑 : 是由成员在构造上修改的,所以我不想用 状态 如果没有设置标志。

    3 回复  |  直到 13 年前
        1
  •  3
  •   Tony Delroy    14 年前

    你必须学会信任编译器的优化器来适当地内嵌这类事物,否则你将限制自己使用99%的标准库和高级C++设施。

    从boost可选API开始:

    ...
    optional(bool condition, T const&);
    ...
    

    A(bool condition, T const& v) : _a(condition, v) { }
    

    …在初始化时使用它。。。

    _a(st.flag1, st.value)
    
        2
  •  1
  •   Nim    14 年前

    似乎使用 boost::optional<> 使事情复杂化,使用它和复制构造的方法似乎会导致 state 基于和基于复制的构造函数 A &安培; B 被调用-即使是完全优化。

    但是,如果我定义 C A _a B _b

    _a(st.flag1? A(st) : A()), _b(st.flag2? B(st) : B())
    

    显然这是最理想的实现方法,我只需要在boost::optional<gt;(即初始化与未初始化)中使用其他功能。

        3
  •  0
  •   Matthieu M.    14 年前

    我希望copy构造函数方法能够工作,因为正如所述,它解决了三元运算符的类型问题。但是我不知道拷贝是否可以优化。

    不过,从可读性的角度来看,我更希望:

    boost::optional<A> buildA(state& st) { return st.flag1 ? A(st) : A(); }
    boost::optional<B> buildB(state& st) { return st.flag2 ? B(st) : B(); }
    
    C::C(state& st): _a(buildA(st)), _b(buildB(st)) {}
    

    更详细一点。拷贝的优化仍然是一个很好的问题。

    你为什么用 state& state const& 因为没有参考资料 st .