【问题标题】:Is it possible to perform I/O in constexpr functions是否可以在 constexpr 函数中执行 I/O
【发布时间】:2019-03-24 23:36:10
【问题描述】:
#include <iostream>

class test
{
public:
    constexpr void setX(int val);
private:
    int x;
};

constexpr void test::setX(int val)
{
    x = val;
    std::cout << "x : " << x << '\n';
}

int main()
{
    test obj;
    obj.setX(5);
    return 0;
}

这里的问题是,我无法在这个 constexpr 函数中执行用于调试的 I/O 操作。那么有什么方法可以在 constexpr 函数中进行 I/O 操作,还是这是 C++ 中的限制/行为?

【问题讨论】:

  • 没有。 constexpr 东西想在编译时计算。

标签: c++ c++11 c++14 constexpr


【解决方案1】:

根据C++11 [dcl.constexpr]p5,目前您的格式不正确,不需要诊断:

对于 constexpr 函数,如果不存在这样的函数参数值 函数调用替换将产生一个常量 表达式 ([expr.const]),程序格式错误;没有诊断 必需的。对于 constexpr 构造函数,如果不存在参数值 这样在函数调用替换之后,每个构造函数 mem-initializers 中的 call 和 full-expression 将是一个常量 表达式(包括转换),程序格式错误;不 需要诊断。 [ 例子:

constexpr int f(bool b)
  { return b ? throw 0 : 0; }               // OK
constexpr int f() { throw 0; }              // ill-formed, no diagnostic required

struct B {
  constexpr B(int x) : i(0) { }             // x is unused
  int i;
};

int global;

struct D : B {
  constexpr D() : B(global) { }             // ill-formed, no diagnostic required
                                            // lvalue-to-rvalue conversion on non-constant global
};

—结束示例]

如果您尝试在需要常量表达式的上下文中使用它,这将成为一个硬错误,例如:

constexpr test obj;

see godbolt example live.

我们可以从[expr.const]p2 看到我们被限制为调用constexpr 函数:

为文字类或 constexpr 函数调用除 constexpr 构造函数之外的函数 [注意:照常应用重载解析 ([over.match]) — 结束注释];

cout和其他I/O函数没有标记constexpr

C++14 的引用类似于[dcl.constexpr]p5[expr.const]p2

【讨论】:

  • 你是对的,但为了完整起见,还有其他方法可以使用std::cout吗?一些编译器“调试”警告(例如通过编译指示)怎么样,但我想不出任何正确的方法来获取某些变量的警告值。
  • @Qeek 相关阅读:constexpr-function-parameters。顺便说一句,如果你坚持它是一个普通的函数参数和一个 constexpr,我不明白你会怎么做。
  • OP 的示例无论如何都是格式错误的 C++11,所以我会继续假设它们正在编译为 C++14。 (“函数调用替换”是 C++11 constexpr 独有的,我不会在 C++14 或更高版本的上下文中提出。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多