У меня есть следующий образец класса Foo
с вложенным классом Bar
и все 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();
}
};
И я хочу проверить, что вызов Foo::DoTheThing
возвращает 1:
int main()
{
constexpr Foo f;
static_assert(f.DoTheThing() == 1, "DoTheThing() should return 1");
}
GCC и Clang здесь жалуются, но MSVC не
GCC говорит:
ошибка:
constexpr Foo::Bar<T>::Bar() [with T = int]
используется перед ее определениемconstexpr static auto b = Bar<int>{};
И Clang:
error: constexpr variable
b
должна быть инициализирована константным выражениемconstexpr static auto b = Bar<int>{};
Я не могу сказать, запретил ли стандарт это, но я предполагаю, что каким-то образом b
является неполным типом.
Что делает вещи более интересными, так это то, что я могу заставить GCC и Clang вести себя, если я удалю constexpr
, или если я переместил определение Bar
вне Foo
.
Какой из этих компиляторов правильный?
Обратите внимание, что этот вопрос был вдохновлен следующим:
- Простой constexpr LookUpTable в С++ 14 (моя проблема - это одна из неотвеченных проблем)
- Вложенные struct breaks constexpr, несмотря на то, что они идентичны глобальным (это, как представляется, дает некоторое представление о том, что происходит)