支持空初始化列表的高效对象构造

时间:2014-12-10 11:05:20

标签: c++ c++11 initializer-list perfect-forwarding

我有一个这样的课程,除了有多个成员:

struct S {
    S( S&& s ) : member( std::move( s.member ) ) {}
    std::vector< int > member;
};

我基本上想要聚合初始化就像这样:

S s{ {} };

但由于自定义构造函数,这似乎是不可能的,所以我想使用构造函数参数来模拟它:

struct S {
    S( S&& s ) : member( std::move( s.member ) ) {}
    S( std::vector< int >&& vec ) : member( std::move( vec ) ) {}
    S( const std::vector< int >& vec ) : member( vec ) {}
    std::vector< int > member;
};

看起来很多冗余只是为了移动,如果可能的话,另外复制,特别是随着排列数量的爆炸,会有更多的成员。我想我想完美转发?

struct S {
    template< typename V >
    S( V&& vec ) : member( std::forward< V >( vec ) ) {}
    S( S&& s ) : member( std::move( s.member ) ) {}
    std::vector< int > member;
};

但现在我无法用一个空的初始化列表来调用它:

S s( {} );

因为无法推导出初始化列表参数类型。有什么解决方案不要求我写

S s( std::vector<int>{} );

1 个答案:

答案 0 :(得分:5)

目前尚不清楚为什么添加默认构造函数不适合您,只允许S s{}

struct S {
    S() = default;
    S( S&& s ) = default;
    std::vector< int > member;
};

如果不合适,您有很多选择。最明显的是摆脱你的移动构造函数,所以这个类是一个聚合。你所展示的移动构造函数无论如何都没有意义,它没有做任何隐式定义的不会做的事情。

struct S {
    std::vector< int > member;
};

下一个选项是添加一个初始化列表构造函数:

struct S {
    S() = default;
    S( S&& s ) = default;
    S(std::initializer_list<int> il) : member(il) { }
    std::vector< int > member;
};

这将允许您将braced-init-list传递给vector成员。

另一个选项,如果你只想将空的初始化列表传递给向量,就是重载构造函数,以便将一些东西传递给向量是可选的(但你仍然可以为其他成员传递参数)。这意味着您只需省略向量的无意义{}参数,并将其设置为默认值。