在定义之前使用 constexpr 函数失败

问题描述 投票:0回答:2

我在

constexpr
方面遇到了一些麻烦。 C++ Primer这本书展示了一行代码:

  constexpr int sz = size(); // only size() is a constexpr function
                             // this code is right

不过书中没有给出具体的例子。所以我自己尝试了以下代码:

#include <iostream>
constexpr int fun();
int main()
{
    constexpr int f = fun();
    std::cout << f << std::endl;
}
constexpr int fun()
{
    return 3;
}

但是 clang 3.1 说

未定义的函数“fun”不能在常量表达式中使用

如果我将

constexpr
更改为
const
,它效果很好,如果我在使用之前更改代码以定义 constexpr 函数:

#include <iostream>
constexpr int fun()
{
    return 3;
}
int main()
{
    constexpr int f = fun();
    std::cout << f << std::endl;
}

效果也很好。有人可以告诉我为什么吗?

c++ constexpr constexpr-function
2个回答
20
投票

constexpr
函数在首次使用之前不必定义,但是在定义之前进行的任何调用的结果都不是常量表达式。

来源:C++ 标准草案 n4296,第 5.20 节:

A 条件表达式

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

  • this
    ,除了作为
    constexpr
    的一部分进行评估的
    constexpr
    函数或
    e
    构造函数;
  • 对文字类的
    constexpr
    构造函数以外的函数的调用、
    constexpr
    函数或普通析构函数的隐式调用 [注意:重载解析应用为 通常 — 尾注];
  • 调用未定义的
    constexpr
    函数
    或未定义的
    constexpr
    构造函数;
  • ...

3485 草案版本(第 5.19 节):

A 条件表达式核心常量表达式,除非它涉及以下内容之一作为潜在计算的子表达式,但不考虑未计算的逻辑 AND、逻辑 OR 和条件运算的子表达式 [ 注意:重载运算符调用函数。 — 尾注]:

  • this
    [ 注意:计算常量表达式时,函数调用替换会将
    this
    成员函数中每次出现的
    constexpr
    替换为指向类对象的指针。 — 尾注];
  • 对文字类或
    constexpr
    函数的
    constexpr
    构造函数之外的函数的调用 [注意:重载解析照常应用 - 尾注];
  • 调用未定义的
    constexpr
    函数
    或未定义的
    constexpr
    构造函数
  • ...

n2235 中的示例

int x2 = s. t();
实际上由于标准化之前所做的更改而变得有效。然而,
constexpr int x2 = s. t();
仍然是一个错误。


3
投票

常量表达式函数必须在首次使用之前定义。请参阅这篇论文,第 4.1 节末尾。

© www.soinside.com 2019 - 2024. All rights reserved.