如何构造不可移动的不可复制对象的元组?

时间:2019-05-17 13:55:02

标签: c++ c++14 c++17

是否可以以某种方式构造这样的tuple

#include <tuple>

struct A
{
    A() = default;
    A(const A&) = delete;
    A(A&&) = delete;
};

auto generate()
{
    // Funktion which constructs a tuple on one line...
    return std::make_tuple(A{},A{});
}

int main()
{
    auto t = generate();
}

在C ++ 14中这是否可能,并且在C ++ 17中这可能会迫使Return-Value-Optimization(未命名的prvalue返回表达式)?

Live

2 个答案:

答案 0 :(得分:3)

tuple的构造函数根据与tuple的模板参数完全相同的类型的参数初始化对象,要求这些类型是可复制构造的。但是,如果所有类型都是默认可构造的,则可以这样做。因此,您只需generate发出return tuple<A, A>{};。这适用于C ++ 17。

如果要使用值初始化它们,则可以使用tuple构造函数,该构造函数使用与tuple参数不同的类型序列进行显式转换。在那里,您可以使用C ++ 17保证的复制省略,但前提是源类型使用operator Type()重载并遵守保证的删除规则。

答案 1 :(得分:1)

std::tuple<A,A> generate() { return {}; }

如果您需要非默认构造A

template<class U, class F>
struct maker_t{ operator U(){ return f(); } F f; };
template<class U, class F>
maker_t<U,std::decay_t<F>> maker(F&& f){ return {std::forward<F>(f)}; }

现在您可以:

std::tuple<A,A> generate() {
  return {
    maker<A>( []{ return A{}; } ),
    maker<A>( []{ return A{}; } )
  };
}

这些lambda可以执行返回A的任何操作。