【发布时间】:2019-07-05 23:16:15
【问题描述】:
考虑以下示例代码:
#include <array>
struct MyClass
{
size_t value = 0;
constexpr static size_t size() noexcept
{
return 3;
}
};
template <size_t N>
void DoIt()
{
MyClass h;
std::array<int, h.size()> arr;
}
int main()
{
DoIt<1>();
}
当我尝试使用 GCC 7.3.0 编译它时,我收到一个关于 h 在非 constexpr 上下文中不可用的错误:
cexpr.cpp: In function ‘void DoIt()’:
cexpr.cpp:17:26: error: the value of ‘h’ is not usable in a constant expression
std::array<int, h.size()> arr;
^
cexpr.cpp:16:11: note: ‘h’ was not declared ‘constexpr’
MyClass h;
^
cexpr.cpp:17:27: error: the value of ‘h’ is not usable in a constant expression
std::array<int, h.size()> arr;
^
cexpr.cpp:16:11: note: ‘h’ was not declared ‘constexpr’
MyClass h;
^
但是,当我尝试在 Clang 6.0.0 中编译完全相同的代码时,它编译时没有任何错误。此外,当我将代码修改为不在模板化 DoIt() 函数内时,GCC 编译它就好了:
#include <array>
struct MyClass
{
size_t value = 0;
constexpr static size_t size() noexcept
{
return 3;
}
};
int main()
{
MyClass h;
// this compiles just fine in Clang and GCC
std::array<int, h.size()> arr;
}
我已经知道如何修复第一个代码,以便它使用decltype 在 GCC 上编译,但我很想知道为什么第一段代码不使用 GCC 编译?这只是 GCC 中的一个错误,还是我对使用 constexpr 静态成员函数有什么不明白的地方?
【问题讨论】:
-
为什么不
MyClass::size()? -
@helloworld922:查看关于 GCC 的类似错误报告。
constexprmember function calls in aconstexprconstructor are ignored if the object is defined locally -
您可以提出一个论点,因为二进制
.表达式的左侧仍然需要在解析之前作为表达式进行评估(例如,我可以这样做(MyClass{} + MyClass{}).size()如果 MyClass 有一个operator+()。h表达式没有副作用这一事实可能会在编译过程中相当晚地崩溃,因此要求它为constexpr并非完全不合理。跨度> -
@Frank 如果是这样,我不明白为什么当我在模板函数的上下文中使用 h.size() 时它无法编译,但在非它编译得很好的模板化函数。
-
对于通过非
constexpr对象调用静态成员函数是否是常量表达式,实现者/专家之间存在一些不确定性。你不应该能够在常量表达式中使用这样的变量,但静态成员函数当然不会真正使用它。
标签: c++ c++14 language-lawyer static-methods constexpr