gpt4 book ai didi

c++ - 具有可移动构造元素的 std::tuple 默认构造函数

转载 作者:行者123 更新时间:2023-12-02 00:39:47 41 4
gpt4 key购买 nike

我正在尝试返回一个 std::tuple ,其中包含不可复制构造类型的元素。这似乎阻止我使用默认的类构造函数来构造元组。例如,要返回包含 Foo 的元组,必须创建 foo 实例,并且 std::moved:

class Foo {
public:
Foo(const Foo&) = delete;
Foo(Foo&&) = default;
int x;
};

tuple<int, Foo> MakeFoo() {
Foo foo{37};
// return {42, {37}}; // error: could not convert ‘{42, {37}}’ from ‘’ to ‘std::tuple’
return {42, std::move(foo)};
}

另一方面,如果类被定义为具有复制构造函数,则元组的构造可以正常工作:

class Bar {
public:
Bar(const Bar&) = default;
int x;
};

tuple<int, Bar> MakeBar() {
return {42, {37}}; // compiles ok
}

有没有办法将 MakeBar 语法与 Foo 类一起使用?

最佳答案

不完全是这样,但你(至少)有两个选择。

您可以拼出 Foo:

tuple<int, Foo> MakeFoo() {
return {42, Foo{37}}
}

或者您可以向 Foo 添加一个构造函数来替换您现在正在执行的聚合初始化:

class Foo {
public:
Foo(const Foo&) = delete;
Foo(Foo&&) = default;
Foo(int x) : x(x) {} // <--
int x;
};

tuple<int, Foo> MakeFoo() {
return {42, 37};
}

但是为什么要写return {42, 37}而不是return {42, {37}}呢?为什么需要添加构造函数才能完成这项工作?

构造一个至少具有一种仅移动类型的元组意味着我们不能使用直接构造函数

tuple<Types...>::tuple(const Types &...)

相反,我们必须使用模板化转换构造函数

template<class... UTypes>
tuple<Types...>::tuple(UTypes &&...)

因此将推导出两个参数的类型。但是,{37} 是一个初始值设定项列表,在本例中,它使第二个函数参数成为非推导上下文(请参阅 [temp.deduct.type]/5.6 )。因此模板参数推导失败,并且构造函数无法被调用。因此,我们必须编写 return {42, 37} 才能让推演成功。

此外,此模板化转换构造函数仅在参数类型可转换为相应的元组元素类型时参与重载决策。并且可转换性不考虑聚合初始化,因此 int 无法转换为原始 Foo。但是,如果我们添加转换构造函数 Foo::Foo(int)int 现在可以转换为 Foo,并且 tuple 可以调用构造函数。

关于c++ - 具有可移动构造元素的 std::tuple 默认构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58614694/

41 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com