4

I am trying to unpack a tuple and use the results to assign into members. Is it possible to do that in idiomatic C++17?

I realize that std::tie exists but I am trying to utilize C++17 features and not default to older features nor the old way (std::get<N>(tuple))

tuple<A, vector<A>> IO(){
     //IO happens here
     return {var, vec};
}

class foo{
public:
    foo();
private:
    A var;
    vector<A> vec;
};

foo::foo(){
    //this line here: I want to assign var and vec from IO()
    [var, vec] = IO();
}
Barry
  • 286,269
  • 29
  • 621
  • 977
  • 4
    Can you tun this into a [mcve]? The code loos like it could work but it is missing stuff. – NathanOliver Mar 13 '19 at 20:10
  • Why ignore the previous versions? I mean are you going to stop using virtual functions because they were in '98? – Gem Taylor Mar 13 '19 at 20:17
  • 3
    @GemTaylor A less hostile interpretation of the question might be: "We have structured bindings in C++17. Does there exist a new, nicer way for me to solve this problem, or do I have to use the old way?" – Barry Mar 13 '19 at 20:20
  • @Barry, That is exactly what I am asking. – Mercutio Calviary Mar 13 '19 at 20:22

1 Answers1

6

Not really. Structured bindings can only declare new names, it cannot assign to existing ones.

Best would be to just do this:

foo() : foo(IO()) { } // delegate to a constructor, calling IO

foo(std::tuple<A, vector<A>>&& tup) // manually unpack within this constructor
  : var(std::get<0>(std::move(tup)))
  , vec(std::get<1>(std::move(tup)))
{ }

If A happens to be default constructible and move assignable, then yeah this works too:

foo() {
    std::tie(var, vec) = IO();
}

If A happens to not be default constructible, then you could use optional to add that extra state:

struct foo {
    std::optional<A> var;
    std::vector<A> vec;

    foo() {
        std::tie(var, vec) = IO();
    }
};

None of these are particularly great.

Barry
  • 286,269
  • 29
  • 621
  • 977