c++ - constexpr 静态成员函数用法

标签 c++ c++14 language-lawyer static-methods 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;
}

我已经知道如何修复第一个代码,以便它使用 decltype 在 GCC 上编译,但我很想知道为什么第一段代码不使用 GCC 编译?这只是 GCC 中的一个错误,还是我对使用 constexpr 静态成员函数有什么不明白的地方?

最佳答案

在我看来是个错误。

表达式h.size()的类型和含义由[expr.ref]“类成员访问”定义:

[expr.post]/3

Abbreviating postfix-expression.id-expression as E1.E2, E1 is called the object expression. [...]

[expr.post]/6.3.1

If E2 is a (possibly overloaded) member function, function overload resolution is used to determine whether E1.E2 refers to a static or a non-static member function.

  • (6.3.1) If it refers to a static member function and the type of E2 is “function of parameter-type-list returning T”, then E1.E2 is an lvalue; the expression designates the static member function. The type of E1.E2 is the same type as that of E2, namely “function of parameter-type-list returning T”.

这意味着 h.size 具有与 ::MyClass::size 相同的类型,并且被评估为这样,不管 hconstexpr 还是不是

h.size() 然后是对 constexpr 函数的调用,并且是根据 [expr.const]/4核心常量表达式 .

关于c++ - constexpr 静态成员函数用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54647876/

相关文章:

c++ - unique_ptr 删除器导致我的程序崩溃

c++ - C++ 图形库的内部工作原理

c++ - 谁能解释一下这个 C++ 程序。结果很奇怪 :(

java - 为什么以及如何编译这个奇怪的方法返回类型?

c++ - 如何在没有模板的情况下将左值传递给仅采用右值的函数

c++ - 返回 NULL 而不是 std::string C++

c++ - 如何测试是否存在模板函数特化

c++ - 为什么自动不检测函数的引用类型

c++ - [ranges.subrange] 中 `iterator-sentinel-pair` 概念的目的是什么?

c++ - C++20 模板ambas 的限制和使用