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 definitionconstexpr static auto b = Bar<int>{};
And Clang:
error: constexpr variable
b
must be initialized by a constant expressionconstexpr 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:
- Simple constexpr LookUpTable in C++14 (my problem is one part of this unanswered question's problem)
- Nested struct breaks constexpr despite being identical to global ones (this seems to provide some insight into what's going on)