constexpr在非const成员函数上的用途是什么?

时间:2018-05-03 07:16:20

标签: c++ c++14 constexpr

literal class compile error with constexpr constructor and function (differ vc, g++)中接受的答案表明,在C ++ 14中,constexpr int A::a()constexpr A::a() const的使用方式存在差异。即成员函数上的constexpr并不意味着该函数不会更改它所作用的对象。

给出的例子是:

struct A {
    constexpr A() {}
    constexpr int a() {return 12; }
    constexpr int b() const {return 12; }
};

int main()
{
    constexpr A a;
    // DOES NOT COMPILE as a() is not const
    // constexpr int j = a.a();
    const int k = a.b(); // Fine since b() is const
}

对我而言,constexpr上的a()似乎毫无用处。 非constexpr成员函数的const是否具体用途?

2 个答案:

答案 0 :(得分:13)

constexpr表示“可用于需要常量表达式的地方”。声明对象的“隐含const”并不意味着我们不能在其他上下文中包含非const对象。例如,一个有点人为的例子,由你自己创建:

template<int>
struct foo {
};

struct A {
    int i = 0;
    constexpr A() {}
    constexpr int a() { return i; }
    constexpr int b() const {return 12; }
    constexpr A&  c() { ++i; return *this; }
};

int main()
{
    foo<A{}.c().a()> f1;
}

显然,模板参数必须是常量表达式。现在,A{}是带有constexpr c'tor的文字类型的prvalue,它是一个非const对象。允许成员函数修改此“常量”,因为整个计算可以在编译时折叠为常量表达式。这是规则的基本原理,一只脚。

答案 1 :(得分:11)

问题:如何创建大小为1024的constexpr数组,其中所有元素都设置为0,但元素元素42除外,需要11

#include <array>

constexpr auto make_my_array() -> std::array<int, 1024>
{
    std::array<int, 1024> a{};
    a[42] = 11; // std::array::operator[] is constexpr non-const method since C++17

    return a;
}

auto test()
{
    constexpr std::array<int, 1024> a = make_my_array();
}

或者来自@ michael-anderson make_iota_array的更好的建议:

template <std::size_t N>
constexpr auto make_iota_array() -> std::array<int, N>
{
    std::array<int, N> a{};

    for (std::size_t i = 0; i < N; ++i)
        a[i] = i;

    return a;
}