【问题标题】:What is the use of a constexpr on a non-const member function?constexpr 在非常量成员函数上的用途是什么?
【发布时间】:2018-05-03 07:16:19
【问题描述】:

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
}

对我来说,a() 上的 constexpr 似乎没用。 constexpr 在非const 成员函数上有具体用途吗?

【问题讨论】:

    标签: c++ c++14 constexpr


    【解决方案1】:

    constexpr 表示“可以在需要常量表达式的地方使用”。声明对象的 "implied 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 的文字类型的纯右值,它是一个非常量对象。允许成员函数修改这个“常量”,因为整个计算可以在编译时折叠成一个常量表达式。这就是规则的基本原理,一只脚。

    【讨论】:

    • 哇。我什至从未意识到这样的事情是可能的。我想我得从 2000 年以前的 C++ 思维模式中解脱出来......
    【解决方案2】:

    问题:如何创建一个大小为 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;
    }
    

    【讨论】:

    • 数字 当有一个更清晰、更简单的示例时,我会用模板制作一些疯狂的东西。 +1。
    • @StoryTeller 和我找到了一个实际的例子
    • @StoryTeller 我认为你为这个问题增加了一个很好的价值,特别是关于常量表达。这次请不要删除它:)
    • 我喜欢这个例子。我想你甚至可以在 for 循环中初始化 a[k]=kmake_iota_array&lt;N&gt;() -&gt; array&lt;int,N&gt; —— 我之前将这种事情编码为糟糕的模板黑客。
    猜你喜欢
    • 2022-01-03
    • 2019-07-09
    • 2015-06-03
    • 1970-01-01
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多