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
bmust 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)