c++ - constexpr 静态成员函数用法
问题描述
考虑以下示例代码:
#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;
}
我已经知道如何修复第一个代码,以便它使用 GCC 在 GCC 上编译decltype
,但我很想知道为什么第一段代码不使用 GCC 编译?这只是 GCC 中的一个错误,还是我对使用 constexpr 静态成员函数有什么不明白的地方?
解决方案
对我来说似乎是一个错误。
表达式的类型和含义h.size()
由[expr.ref]
“类成员访问”定义:
[expr.post]/3
将 postfix-expression.id-expression缩写为
E1.E2
,E1
称为对象表达式。[...]
和
[expr.post]/6.3.1
if
E2
是一个(可能重载的)成员函数,函数重载决议用于确定是E1.E2
指静态成员函数还是非静态成员函数。
- (6.3.1) 如果引用的是静态成员函数,且类型
E2
为“参数类型列表返回函数T
”,E1.E2
则为左值;表达式指定静态成员函数。的类型与 的E1.E2
类型相同E2
,即“参数类型列表返回函数T
”。
这意味着h.size
具有相同的类型::MyClass::size
并且被评估为这样,无论h
是constexpr
与否。
h.size()
然后是对constexpr
函数的调用,并且是根据的核心常量表达式[expr.const]/4
。
推荐阅读
- apache-spark - 错误执行程序:阶段 1.0 中任务 52.0 中的异常 (TID 200)
- nosql - 重命名文档密钥 Arango DB
- machine-learning - RDF 存储上的机器学习以检测模式
- php - 在 JMS 序列化程序中混合访问器和 SkipWhenEmpty
- python - 如何使用 Python 从容器内的文本中刮取 Td
- openstreetmap - 有没有办法在 OSRM 服务器中使用从 openstreetmap 导出的地图图块?
- wordpress - WooCommerce REST API 通过电话号码获取客户
- c++ - 虚函数覆盖是否违反 LSP?
- c# - 如何在 Tfs 的 TeamProject 中创建 Git 存储库?
- flutter - 如何在 FutureBuilder 项目的 Flutter ListView 中向上滚动时修复“跳到每个项目的顶部”?