I have the following sample class Foo
with nested class Bar
and everything is constexpr
:
class Foo
{
private:
template <typename T>
struct Bar
{
constexpr Bar(){}
constexpr int DoTheThing() const
{
return 1;
}
};
public:
constexpr static auto b = Bar<int>{};
constexpr Foo() {}
constexpr int DoTheThing() const
{
return b.DoTheThing();
}
};
And I want to test that calling Foo::DoTheThing
returns 1:
int main()
{
constexpr Foo f;
static_assert(f.DoTheThing() == 1, "DoTheThing() should return 1");
}
GCC and Clang both complain here, but MSVC does not
GCC says:
error: constexpr Foo::Bar<T>::Bar() [with T = int]
used before its definition
constexpr static auto b = Bar<int>{};
And Clang:
error: constexpr variable b
must be initialized by a constant expression
constexpr static auto b = Bar<int>{};
I cannot tell if the standard disallows this, but my guess is that somehow b
is an incomplete type.
What makes things more interesting is that I can get GCC and Clang to behave if I remove the constexpr
, or if I move the definition of Bar
outside of Foo
.
Which of these compilers is correct?
Note that this question was inspired by the following:
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…