调用模板参数constexpr方法?

时间:2018-08-21 07:08:45

标签: c++ c++11 templates language-lawyer constexpr

std::array<...>::size()是非static constexpr方法;作为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

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


P.S。 是的,我知道我可以使用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;
}

1 个答案:

答案 0 :(得分:3)

C语是正确的。

您正在评估的引用类型的id表达式(a)没有预先的初始化,这在常量表达式中是不允许的。

[expr.const]/2

  

表达式e核心常量表达式,除非根据抽象机的规则对e的求值将对以下表达式之一求值:      

      
  • ...

  •   
  • 一个 id-expression ,它引用引用类型的变量或数据成员,除非该引用具有先前的初始化,并且其中一个都具有

         
        
    • 使用常量表达式或

    • 初始化   
    • 其生存期始于e的评估;

    •   
  •   
  • ...

  •