【问题标题】:constexpr array reference parameterconstexpr 数组引用参数
【发布时间】:2013-10-24 10:22:36
【问题描述】:

谁能解释一下为什么下面的标记行编译得很好:

template<typename T, int N>
constexpr
int get_size(T (&)[N])
{
    return N;
}

int main()
{
    int xs[10];
    constexpr int y = get_size(xs); // HERE.
    static_assert(10 == y, "wrong size");
}

凭直觉,get_size(xs) 不是一个常量表达式,因为 xs 本身不是,所以我不明白它为什么起作用。

【问题讨论】:

  • xs 的大小是一个编译时间常数,这是函数模板为你得到的。
  • @juanchopanza 我想我很困惑为什么地址未知的自动变量可以通过引用常量表达式中使用的函数来传递。

标签: c++ arrays c++11 constexpr


【解决方案1】:

您的问题和评论:

我想我很困惑为什么地址未知的自动变量可以通过引用在常量表达式中使用的函数来传递

当编译器看到get_size(xs)时,它已经解析了int xs[10];的前一行,因此知道xs的类型和大小。就 typesize 而言,在运行时什么都不会改变——这两个是编译所需的信息为了实例化函数模板,所以实例化函数模板不会遇到任何问题,在这种情况下,函数模板的行为类似于constexpr,因为在编译时一切都是已知的,这就是static_assert 不会失败的原因.

【讨论】:

    【解决方案2】:

    模板函数被实例化后你的程序就变成了下面这样:

    constexpr
    int get_size(int (&)[10])
    {
        return 10;
    }
    
    int main()
    {
        int xs[10];
        constexpr int y = get_size(xs); // HERE.
        static_assert(10 == y, "wrong size");
    }
    

    那么在函数调用替换之后就变成了等价于:

    int main()
    {
        int xs[10];
        constexpr int y = 10; // HERE.
        static_assert(10 == y, "wrong size");
    }
    

    函数调用替换在 7.1.5 [dcl.constexpr]/5 中描述。本质上,参数就像复制初始化一样被替换,然后替换为返回表达式中的出现。然后返回表达式同样如同复制初始化返回值一样。然后,生成的表达式将成为替换函数调用的表达式。只有 after this 是满足上下文放置的常量表达式的约束时才考虑的表达式。 (注意,高质量的编译器当然可以确定 constexpr 函数在任何此类操作后永远无法成功使用,并且在遇到函数定义后可能会失败,但并非必须如此)

    另外请注意,为了让您感到困惑,这个概念在 C++14 中被删除,并用一个不同的概念来代替 constexpr 函数的求值方式。除其他外,您将能够在 constexpr 函数中使用 if 语句、for 语句和文字类型的局部变量。

    【讨论】:

    • 我想我刚刚得到了一个稍微相关的启示:这是否意味着您可以在 constexpr 函数中执行“非常量表达式”的事情,只要它实际上不是执行。 IE。为什么constexpr int x = (false ? std::puts("Hello") : 0, 0); 也可以,为什么throwing 会导致编译时错误(我认为throw 是经过特殊处理的,但可能不是)。
    • @Simple:false ? std::puts("Hello") : 0 是一个常量表达式。参见 5.19 常量表达式 [expr.const]。 LHS 不被评估,因此不在条件表达式中考虑。
    • 这很酷。这意味着您可以在constexpr 函数中使用assert,具体取决于宏的实现方式(或者您可以编写自己的#define ASSERT(x) ((x) ? void() : ::std::abort()))并初始化constexpr 变量会给您一个编译错误,否则会导致运行时错误。
    • 看起来比其他答案好多了,这对我来说太常识了,标准证明太少了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-28
    • 1970-01-01
    相关资源
    最近更新 更多