flyfisher
flyfisher

Reputation: 77

Is there a way to move a std::tuple into a struct?

Say I have a struct and a tuple with identical fields:

struct foo {
  int x;
  std::string y;
  some_big_type z;
};

std::tuple<int, std::string> a{1, "hello", some_big_type{...}};

Is there a way to move-construct a foo object using a? By which I mean, I don't want to allocate new memory for a foo, but rather to construct a foo which acts as a "view" on the already-allocated tuple.

Upvotes: 1

Views: 260

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275360

In this is just std::make_from_tuple<foo>(a).

Prior to you have to write your own helper.

template<class T, std::size_t...Is, class Tuple>
T aggregate_from_tuple( std::index_sequence<Is...>, Tuple&& tuple ) {
  return { std::get<Is>( std::forward<Tuple>(tuple) )... };
}
template<class T, class Tuple>
T aggregate_from_tuple( Tuple&& tuple ) {
  auto indexes = std::make_index_sequence<
    std::tuple_size_v<std::decay_t<Tuple>>
  >{};
  return aggregate_from_tuple<T>(indexes, std::forward<Tuple>(tuple))
}

which is basically make_from_tuple with () replaced with {}. In you can use () to initialize aggregates.

The older the version of C++ it is the more verbose the above is going to get. Prior to I am not sure I could do it; the above is probably .

This does NOT produce a view into the tuple. It either copies it to a foo or (if you use std::move) moves it into the foo.

Often moving a type is cheap when copying is expensive.

There is no great way to create a view. But a non-great way is this:

struct foo_view {
  int& x;
  std::string& y;
  some_big_type& z;
};

which isn't your foo type. This is a non-owning view of something.

Then you use aggregate_from_tuple (or make_from_tuple) the same way, and you'll get an object that provides (near zero) cost renames.

Upvotes: 5

Related Questions