Как построить кортеж из неподвижных, не копируемых объектов? - PullRequest
2 голосов
/ 17 мая 2019

Можно ли как-то построить такую ​​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, что вызывает оптимизацию возвращаемого значения (безымянное выражение возврата prvalue) ??

Живите

Ответы [ 2 ]

3 голосов
/ 17 мая 2019
Конструктор

tuple, который инициализирует объекты из аргументов точно таких же типов, что и параметры шаблона tuple, требует, чтобы эти типы были копируемыми. Однако, если все типы являются конструируемыми по умолчанию, то вы можете сделать это. Таким образом, вы могли бы просто generate выдать return tuple<A, A>{};. Это работает в C ++ 17.

Если вы хотите инициализировать их значением, вы можете использовать конструктор tuple, который использует явное преобразование из последовательности типов, которые не совпадают с параметрами tuple. Там вы можете использовать C ++ 17 гарантированное копирование, но только если в исходных типах используется перегрузка operator Type() и они следуют правилам гарантированного разрешения.

2 голосов
/ 17 мая 2019
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{}; } )
  };
}

, где эти лямбды могут делать все, что возвращает A.

...