This is similar in vein to Is it possible to use structured binding in the member initializer list of a constructor?, except that in my case, it is not a dislike-versus-like scenario rather it is a how-to-solve-it question.
I have two classes that I cannot touch and a free-standing function that constructs one object of each type and returns them as a pair:
#include <utility>
struct A
{
A() = delete;
explicit A(int) {}
};
struct B
{
B() = delete;
explicit B(char) {}
};
std::pair<A, B> func() // Same issue when pair is replaced with tuple
{
return { A{42}, B{'F'} };
}
I can touch neither A
nor B
. func()
does a good amount of common work to construct objects of A
and B
.
Now to the problem at hand, showing my different attempts:
Attempt 1: Try structured binding in ctor initializer-list
class Foo
{
A a;
B b;
public:
Foo() : [a, b] { func() }
// error: expected identifier before '[' token
// Not resolved when '{func()}' is replaced with '= func()' or '(func))'
{
}
};
Attempt 2: Use std::tie
in lieu of structured binding
class Foo
{
A a;
B b;
public:
Foo() : std::tie(a, b) = func() }
// error: expected class-name before '(' token at column 21
{
}
};
Attempt 3: Construction within body, but (of course) it won't work
// error: use of deleted functions 'A::A()' and 'B:B()'
class Foo
{
A a;
B b;
public:
Foo()
{
const auto& p{func()};
a = p.first;
b = p.second;
}
};
The traditional approach is to use a delegating constructor.
class Foo
{
A a;
B b;
Foo(std::pair<A, B> p) : a(p.first), b(p.second) {}
public:
Foo() : Foo(func()) {}
};