为什么我不能在函数中使用constexpr值,但我可以在此值的范围内执行相同的操作?

Ale*_*lex 9 c++ compile-time constexpr c++11 c++14

我不能在函数中使用constexpr值,而不是函数外部.

  • 我可以auto ar1 = std::array<int, il.size()>();il定义的范围内使用.

  • 但我不能使用{ return std::array<T, il.size()>();}in constexpr-functionil_to_array()

为什么我不能在函数中使用constexpr值,但我可以在此值的块范围内执行相同的操作?

http://ideone.com/5g0iRE

#include <iostream>
#include <initializer_list>
#include <array>

constexpr size_t size_to_size(size_t v) { return v; }   // 1 - OK

template<typename T>
constexpr size_t il_to_size(std::initializer_list<T> il) { return il.size(); }  // 2 - OK

// 3 - error
template<typename T>
constexpr auto il_to_array(std::initializer_list<T> il) {return std::array<T, il.size()>();}

template<size_t N>
void print_constexpr() { std::cout << N << std::endl; }

int main() {

    constexpr std::initializer_list<int> il = { 1, 2, 3 };
    print_constexpr<il.size()>();   // 0 - OK

    print_constexpr< size_to_size(il.size()) >();   // 1 - OK

    print_constexpr< il_to_size(il) >();    // 2 - OK

    auto ar1 = std::array<int, il.size()>();    // OK - body of function: il_to_array()

    //auto ar2 = il_to_array(il);   // 3 - error

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

例如,我们看到,template-constexpr-function不会失败,即使它可能是也可能不是constexpr- 取决于T,因为实例之一可能是constexpr:为什么C++编译器可以声明一个函数作为constexpr,哪个不能constexpr?

  • 并且可以得出结论,如果这是模板函数,则它可以是以下任何一个的特化:constexpr和非constexpr.

  • 并且在SFINAE的基础上- 如果我们仅使用constexpr-arguments然后仅实例化constexpr-instance,并且constexpr无法实例化非功能无关紧要.

Jar*_*d42 8

(constexpr)函数的参数不是constexpr.

constexpr 函数可能会被赋予在编译时未知的参数.

因此,无论是否v在编译时都知道,以下是有效的

constexpr size_t size_to_size(size_t v) { return v; }
Run Code Online (Sandbox Code Playgroud)

但是,以下功能不起作用的ilconstexpr和非类型模板参数需要在编译时被称为:

template<typename T>
constexpr auto il_to_array(std::initializer_list<T> il) {return std::array<T, il.size()>();}
Run Code Online (Sandbox Code Playgroud)

即使仅在编译时使用已知参数调用函数,也是如此.

  • 呃...我不确定这个故事会因为OP的问题而结束...... [Clang](http://coliru.stacked-crooked.com/a/e5440da7ff6a1316)和[MSVC](http:// webcompiler. cloudapp.net/)无法编译OP的代码(只有gcc这样做).他们拒绝它,因为他们不考虑创建`std :: initializer_list <int>`a constexpr` ..我相信:因为标准不清楚它是`constexpr`除了它的成员函数.另一个支持逻辑,如果`T`在`std :: initializer_list <T>`中不能初始化为`constexpr`,该怎么办? (2认同)