I have come across a case of constexpr
usage where I don't understand why the code compiles. Here is a minimal and reproducible example (Godbolt):
struct A
{
A(int a_)
:m_a{a_}
{
}
int m_a;
};
// Compilation fails with this structure:
struct B
{
constexpr B(A a_)
:m_a{a_}
{
}
A m_a;
};
// Compilation OK here, even if A is not constexpr.
struct BOK
{
constexpr BOK(const A& a_)
:m_a{a_}
{
}
A m_a;
};
int main()
{
// constexpr A a{2}; // Fails. OK, A's constructor is not constexpr
// constexpr B b{A(2)}; // Fails. OK, A's constructor is not constexpr
// constexpr BOK bok{A(2)}; // Fails. OK, A's constructor is not constexpr
const BOK bok{A(2)};
return 0;
}
I understand that B
does not compile and the error is clear:
error: invalid type for parameter 1 of 'constexpr' function 'constexpr B::B(A)'
What I don't understand if why BOK
does compile (especially since B
doesn't). It seems the const&
somehow makes it OK for the compiler. As I am showing in the main
function, trying to instantiate a constexpr
version of BOK
fails to compile with error:
error: the type 'const BOK' of 'constexpr' variable 'bok' is not literal
as expected, but the struct's definition seems to be fine. It is weird because is seems the compiler thinks there might be a possibility for this to be constexpr
... Is there? Why does this work?
I have tried this with both g++
and clang
with the -std=c++20
switch.