I have two classes, each constructible from the other.
Example:
class B;
class A{
public:
double val;
constexpr A(B b): val(b.val){};
};
class B{
public:
double val;
constexpr B(A a): val(a.val){};
};
I need to forward-declare class B
, so A knows about it. When these constructors are not constexpr
, I can move their definitions to a source file and it happily compiles.
However, to make it constexpr, they have to be defined in the header. B
is ok to construct from A
, because it sees the full definition of A
. A
cannot construct from B
because it only sees a declaration, and therefore has no idea about B::val
.
I'm left with only making class B
constexpr
. Is there a way to do it for both classes?
Using gcc I get the error (https://godbolt.org/z/qvP7absdr):
<source>:6:15: error: 'b' has incomplete type
6 | constexpr A(B b) : val(b.val){};
| ~~^
<source>:1:7: note: forward declaration of 'class B'
1 | class B;
| ^
<source>: In constructor 'constexpr A::A(B)':
<source>:6:11: error: invalid type for parameter 1 of 'constexpr' function 'constexpr A::A(B)'
6 | constexpr A(B b) : val(b.val){};
| ^
Compiler returned: 1
So this fails because type B
is incomplete when it is used it is the definition of the constructor A::A(B b)
.
In order to deal with this we can wait until we have declared B
fully before we define the constructor and use B. Essentially, move the definition of the constructor out of class A
and after class B
class B;
class A{
public:
double val;
constexpr A(B b);
};
class B{
public:
double val;
constexpr B(A a): val(a.val){};
};
constexpr A::A(B b) : val(b.val){};
See an example without compilations issues: https://godbolt.org/z/44fbcr8sh