这个简单的结构应该有一个隐式移动构造函数吗?

时间:2015-08-26 10:05:38

标签: c++11 language-lawyer

在这个测试中:

#include <string>

struct thing {
    std::string name_;
};

class test {
    thing id_;
public:
    test(thing id) : id_{std::move(id)} {}
};

我希望 struct thing 具有隐式移动构造函数,以便类test 可以使用std :: move()来初始化其数据成员。

Clang 3.4.1版给出了这个错误:

error: no viable conversion from 'typename remove_reference<thing&>::type' (aka 'thing') to 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >')

可以通过向 struct thing 添加移动构造函数来解决问题,这当然也意味着还需要添加转换构造函数和显式默认的复制构造函数。

我不明白为什么我不能隐含地移动 struct thing

1 个答案:

答案 0 :(得分:3)

您正在使用大括号初始化 - id_{std::move(id)}。在您的情况下,好像struct thing是POD(普通旧数据),这意味着C ++编译器尝试初始化第一个成员 - std::string name_而不是使用struct thing对象的默认构造函数。 Read more about aggregates and PODs

在这种情况下,由于大括号,class test的构造函数等效于:

class test {
    thing id_;
public:
    test(thing id) {
        id_.name_ = std::move(id); // Notice that this causes
                                   // the "no viable conversion" error
    }
};

解决方案1:您需要使用括号而不是大括号明确声明您要使用默认的struct thing构造函数:

#include <string>

struct thing {
    std::string name_;
};

class test {
    thing id_;
public:
    test(thing id) : id_(std::move(id)) {} // Default c-tor will be used
};

解决方案2:您还可以声明struct thing的用户定义构造函数,使其成为非POD:

#include <string>

struct thing {
    std::string name_;
    thing(thing&&) {} // Used-defined move constructor
};

class test {
    thing id_;
public:
    test(thing id) : id_{std::move(id)} {} // You can use braces again
};