[英]Constexpr static member function usage
Consider the following example code: 请考虑以下示例代码:
#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>();
}
When I try to compile this with GCC 7.3.0, I get an error about h not being usable in a non-constexpr context: 当我尝试使用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;
^
However, when I try compiling the exact same code in Clang 6.0.0, it compiles without any errors. 但是,当我尝试在Clang 6.0.0中编译完全相同的代码时,它编译时没有任何错误。 Additionally, when I modify the code to not be inside the templated DoIt()
function, GCC compiles this just fine: 另外,当我修改代码不在模板化的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;
}
I already know how to fix the first code so it compiles on GCC using decltype
, but I'm curious to know why doesn't the first piece of code compile with GCC? 我已经知道如何修复第一个代码,所以它使用decltype
在GCC上编译,但我很想知道为什么第一段代码不能用GCC编译? Is this just a bug in GCC, or is there something I don't understand about using constexpr static member functions? 这只是GCC中的一个错误,还是我对使用constexpr静态成员函数有些不了解?
Looks like a bug to me. 对我来说看起来像个错误。
The type and meaning of the expression h.size()
is defined by [expr.ref]
"Class member access": 表达式h.size()
的类型和含义由[expr.ref]
“类成员访问”定义:
[expr.post]/3
Abbreviating postfix-expression.id-expression as
E1.E2
,E1
is called the object expression. 将postfix-expression.id-expression缩写为E1.E2
,E1
称为对象表达式。 [...] [...]
and 和
[expr.post]/6.3.1
If
E2
is a (possibly overloaded) member function, function overload resolution is used to determine whetherE1.E2
refers to a static or a non-static member function. 如果E2
是(可能是重载的)成员函数,则使用函数重载E1.E2
来确定E1.E2
是指静态成员函数还是非静态成员函数。
- (6.3.1) If it refers to a static member function and the type of
E2
is “function of parameter-type-list returningT
”, thenE1.E2
is an lvalue; (6.3.1)如果它引用静态成员函数并且E2
的类型是“参数类型列表返回T
函数”,则E1.E2
是左值; the expression designates the static member function . 表达式指定静态成员函数 。 The type ofE1.E2
is the same type as that ofE2
, namely “function of parameter-type-list returningT
”.E1.E2
的类型与E2
类型相同,即“参数类型列表返回T
函数”。
This means h.size
has the same type as ::MyClass::size
and is evaluated as such, regardless of the fact that h
is constexpr
or not . 这意味着h.size
与::MyClass::size
具有相同的类型,并且无论h
是constexpr
还是not , 都会被评估。
h.size()
is then a call to a constexpr
function and is a core constant expression according to [expr.const]/4
. 然后, h.size()
调用constexpr
函数,并且是[expr.const]/4
的核心常量表达式 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.