【问题标题】:Accessing non-const data members from constexpr member function从 constexpr 成员函数访问非常量数据成员
【发布时间】:2022-01-03 06:27:18
【问题描述】:

GCC 和 MSVC 似乎都允许为非常量数据成员定义 constexpr 访问器函数:

#include <random>
#include <iostream>

class Foo
{
    int val;

public:
    Foo(int v) : val(v) {}

    constexpr int get_val() { return val; } // OK
};

int main()
{
    std::random_device rd;
    Foo foo((int)rd());
    std::cout << foo.get_val(); // works
}

这是来自 MSVC 和 GCC 的非标准行为,还是标准实际上允许这样做?

【问题讨论】:

  • constexpr 不需要在编译时评估函数。更多的是constexpr-preserving——如果输入是常量表达式,那么输出也是常量表达式。在这种情况下,这意味着您可以在constexpr Foo 上调用get_val,但没有什么能阻止您在其他时间调用它。 (实际上,不能在 constexpr Foo 上调用此特定函数,除非它同时是 constexprconst,但您可以在 constexpr 上下文中调用它。)
  • 很有趣,所以 constexpr 要求更多的是它必须可能在编译时在给定适当输入的情况下进行评估?

标签: c++ gcc visual-c++ constexpr


【解决方案1】:

这当然是允许的! constexpr 不代表const。你甚至可以在 constexpr 函数中改变值:

class Foo
{
    int val;

public:
    constexpr Foo(int v) : val(v) {} // OK

    constexpr int get_val() { return val; } // OK
    constexpr void set_val(int v) { val = v; } // OK
};

有了这个,你可以编写看起来像普通函数的 constexpr 函数,只是它们可以在编译器运行时在编译时执行。

constexpr int test() {
    Foo f{};

    f.set_val(2);

    return f.get_val();
}

static_assert(test() == 2); // Checks at compile time

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 2020-03-10
    • 2015-04-01
    • 2019-08-02
    相关资源
    最近更新 更多