自定义交换样板

时间:2014-02-28 10:36:58

标签: c++ boilerplate

我理解复制和交换习惯用法,它有一个需要bolierplate代码的缺点。考虑一个简单的“只持有所有那些该死的柠檬”结构:

struct MuchData {
private:
    std::string one, two;
    int three;
    std::vector<Something> four;
    MyType five;
    MyOtherType six, seven;
    unsigned long long int still_overflows;

public:
    MuchData() : one("."), two("/"), three(0), four(), five(), six(-1), seven(0), still_overflows(0) 
    { }

    MuchData(const MuchData& rhs) : one(rhs.one), two(rhs.two), three(rhs.three), four(rhs.four), five(rhs.five), six(rhs.six), seven(rhs.seven), still_overflows(rhs.still_overflows) 
    { }

    MuchData(MushData&& old) : one("."), two("/"), three(0), four(), five(), six(-1), seven(0), still_overflows(0)
    { swap(*this, old); }

    MuchData& operator=(MuchData old) { swap(*old, this); return *this; }

    friend void swap(MuchData& left, MushData&right) {
        using std::swap;

        swap(left.one, right.one);
        swap(left.two, right.two);
        swap(left.three, right.three);
        swap(left.four, right.four);
        swap(left.five, right.five);
        swap(left.six, right.six);
        swap(left.seven, right.seven);
        swap(left.still_overflows, right.still_overflows);
    }

    // And now we can go and do something interesting
};

使用

编写的初始化程序
: one(".")
, two("/")
, three(0)
// etc.

样式,此代码占用更多空间。 MyTypeMyOtherType可能也是用这种技术定义的......有什么办法可以减少重复性的数量吗?例如,当添加新字段时,很容易忘记添加相应的swap(...)行,这会导致神秘的切片。

2 个答案:

答案 0 :(得分:2)

您可以做的一件事是将成员存储在std::tuple中,并为他们提供命名的访问者,如下所示:

struct MuchData {
private:
  std::tuple<std::string, std::string, int, std::vector<Something>, MyType, MyOtherType, unisgned long long> data;

  std::string& one() { return std::get<0>(data); }
  const std::string& one() const { return std::get<0>(data); }

  //etc.
};

是的,你正在为另一个交换一块样板,但你只会写一次名字;例如,构造函数语法将更加简洁。即使您忘记添加访问者,swap()也会正常工作(因为它只会swap()元组。

使用C ++ 1y,您甚至可以使用auto&const auto&作为访问者的返回类型,从而消除更多重复。

答案 1 :(得分:1)

您可以使用类内初始值设定项来减少将字段初始化为其标准值的构造函数之间的重复:

class MuchData {
  std::string one{"."};
  std::string two{"/"};
  // ...

然后默认和移动构造函数变得微不足道。

MuchData() = default;

MuchData(MuchData&& o) { swap(*this, o); }

您可以默认复制构造函数:

  MuchData(const MuchData&) = default;