调用模板参数 constexpr 方法?

calling a template parameter constexpr method?

本文关键字:方法 constexpr 参数 调用      更新时间:2023-10-16

std::array<...>::size()是一种非staticconstexpr方法;constexpr我可以将其用作模板参数:

#include <array>
#include <stdio>
int main(void) {
std::array<char, 12> a = {{ "Hello world" }};
std::cout << "size() = " << a.size() << ", data() = "" << a.data() << """ << std::endl;
std::array<char, a.size()> b = a;
std::cout << "size() = " << b.size() << ", data() = "" << b.data() << """ << std::endl;
}

但是,如果std::array<...>是模板参数,则情况变得不确定:

template <typename T>
void copy(T const& a) {
std::array<char, a.size()> c = a;
std::cout << "size() = " << c.size() << ", data() = "" << c.data() << """ << std::endl;
}

GCC愉快地编译了这个[1],而CLANG拒绝了[2]

<source>:6:20: error: non-type template argument is not a constant expression
std::array<char, a.size()> c = a;

[1] https://godbolt.org/z/Ru7Y3F
[2] https://godbolt.org/z/LYJcpo

根据标准,哪一个是正确的?


附言 是的,我知道我可以使用std::tuple_size来解决它:

template <typename T>
void copy(T const& a) {
std::array<char, std::tuple_size<T>::value> c = a;
std::cout << "size() = " << c.size() << ", data() = "" << c.data() << """ << std::endl;
}

Clang 是正确的。

您正在计算引用类型的 id 表达式 (a(,该表达式没有前面的初始化,这在常量表达式中是不允许的。

[expr.const]/2:

表达式e核心常量表达式,除非按照抽象机器的规则计算e将计算以下表达式之一:

  • 引用
  • 引用类型的变量或数据成员的ID 表达式,除非引用具有前面的初始化,并且

    • 它使用常量表达式或

    • 它的生命周期始于对e的评估;