编译器错误还是我错误地使用了 constexpr?

问题描述 投票:0回答:1

我不知道我在这里做错了什么: 链接到上帝螺栓

template <int... ints>
struct list {};

// template <int dummy>
struct Obj
{
    static constexpr int var0() { return 0; } 
    list<var0()> data;
};


int main(){}

这无法编译。我收到此错误:

<source>:8:14: error: 'static constexpr int Obj::var0()' called in a constant expression before its definition is complete
    8 |     list<var0()> data;
      |          ~~~~^~
<source>:8:14: note: in template argument for type 'int'
Compiler returned: 1

如果我取消注释它编译的虚拟模板参数...为什么?

c++ c++20
1个回答
0
投票

这与“完整的类上下文”有关,并且是 C++ 的一个微妙问题。成员函数的内联定义只是语言允许的语法糖,这样您在类外部定义函数时就不必重复自己。如果你写 struct Obj { static constexpr int var0() { return 0; } };

你真正得到的是

struct Obj { static constexpr int var0(); }; constexpr int Obj::var0() { return 0; }

这意味着当你尝试拥有

struct Obj { static constexpr int var0() { return 0; } list<var0()> data; };

当您尝试定义 
data

时,该类不被认为是完整的,因此您无法访问

var0
的功能。

当您将其设为模板时,代码会进行编译的原因是模板被“编译”了两次。第一次只是检查语法是否正确。第二遍发生在模板实例化之后,然后检查类的语义。如果您尝试实例化模板,您会得到相同的错误:
https://godbolt.org/z/5TdfWsfY5

© www.soinside.com 2019 - 2024. All rights reserved.