Member initializer list: initialize two members from a function that returns a tuple

Is it possible to initialize several elements in the list of member initializers from the tuple obtained by the function?

With the return of several values ​​through tuples, it becomes more and more popular, I hope there is a solution for this. I see no reason other than limiting the language, because it is impossible.


This is mcve for what I have:

auto new_foo(std::size_t size) -> std::tuple<std::unique_ptr<char[]>, int*> { auto buffer = std::make_unique<char[]>(size * sizeof(int) + 8); auto begin = static_cast<int*>(static_cast<void*>(buffer.get() + 4)); return std::make_tuple(std::move(buffer), begin); } struct X { std::unique_ptr<char[]> buffer_{nullptr}; int* begin_{nullptr}; std::size_t size_{0}; X(std::size_t size) : size_{size} { std::tie(buffer_, begin_) = new_foo(size); } }; 

Can this be done ?:

  X(std::size_t size) : buffer_{ ??? }, begin_{ ??? }, size_{size} { } 

I just can't call new_foo once for each member initialization (since it returns a different tuple with each call). So

  X(std::size_t size) : buffer_{std:get<0>(new_foo(size)}, begin_{std:get<1>(new_foo(size)}, size_{size} { } 

this is impossible (even if it is not, calling several times to get the same result is less than optimal)

Another solution that I was thinking about was to keep the members as a tuple. I dropped this because I need two members correctly named inside the class and not having access to get<0> and get<1> .

Another workaround would be to create a simple separate structure for storing two elements. So they will have names, but add another qualifier level, and maybe I will have to create a copy of ctor for it (due to unique_ptr ).


As reported here, C++1z will have structured bindings (D0144R0) that will make this possible:

 auto {x,y,z} = f(); 

Since I did not find the complete document, I cannot say if this will help in the context of the list of member initializers. I do not suspect.

+7
c ++ tuples c ++ 14 initialization-list c ++ 17
source share
1 answer

Define another (possibly private) constructor that takes the tuple and delegates it.

  private: X(std::tuple<std::unique_ptr<char>, int*> t, std::size_t size) : buffer_{std::move(std:get<0>(t))}, begin_{std:get<1>(t)}, size_{size} { } public: X(std::size_t size) : X{new_foo(size), size} { } 
+14
source share

All Articles