【问题标题】:Return object from constexpr?从 constexpr 返回对象?
【发布时间】:2018-02-05 14:18:23
【问题描述】:

如何从 constexpr 函数返回对象?根据this 你不能使用new 但那我该怎么做呢?有可能吗?我想使用函数的参数来初始化一个对象并返回它,但似乎无法弄清楚如何。

例子:

struct Test {
    int a;
    constexpr Test (int b): a(b) {};
    Test(const Test& a);
};

Test::Test(const Test& t) {
    this->a = t.a;
}

constexpr Test set_test(int a) {
    return Test(a);
}

int main() {
    return 0;
}

【问题讨论】:

  • 为什么你的想法马上跳到new
  • 您想解决的实际问题是什么? 为什么你要使用constexpr函数和new?这是XY-problem question
  • 函数可以按值返回对象。
  • 在这种情况下,请向我们展示一个重现您的错误的最小示例。
  • 操作员new 具有放射性。它只能由受过如何将其包裹在混凝土和铅中的培训的专家处理。自 cfront(1984 年)以来,我一直在使用 C++ 编程,而且我认为自 C++98 以来我只使用过一次“new”。那是在编写自定义分配器。

标签: c++ static constexpr


【解决方案1】:

我对暴露的示例代码做了一点补充,以利用 set_test() 并防止优化死代码:

#include <iostream>

struct Test {
    int a;
    constexpr Test (int b): a(b) {};
    Test(const Test& a);
};

Test::Test(const Test& t) {
    this->a = t.a;
}

constexpr Test set_test(int a) {
    return Test(a);
}

int main() {
  std::cout << "set_test(1).a: " << set_test(1).a << std::endl;
    return 0;
}

这在ideone 中运行良好。

声明使用C++ (gcc 6.3)

因此,我正在寻找另一个在线编译,我可以在其中选择 clang 并找到 Wandbox

clang HEAD 7.0.0 编译失败。如果我做对了set_test() 尝试使用不是constexpr 的复制构造函数。

因此,我deleted 复制构造函数。现在,它在return Test(a); 中失败了,因为它试图访问已删除的复制构造函数。奇怪……

所以,我终于提供了一个移动构造函数

constexpr Test(Test &amp;&amp;test): a(test.a) { }

作为已删除的复制构造函数的替换。现在,它可以编译并运行了:

#include <iostream>

struct Test {
    int a;
    constexpr Test (int b): a(b) {}
    Test(const Test& a) = delete;
    constexpr Test(Test &&test): a(test.a) { }
};

#if 0
Test::Test(const Test& t) {
    this->a = t.a;
}
#endif // 0

constexpr Test set_test(int a) {
    return Test(a);
}

int main() {
  std::cout << "set_test(1).a: " << set_test(1).a << std::endl;
    return 0;
}

输出:

Start

set_test(1).a: 1

0

Finish

Wandbox 上的生活演示。


出于好奇,我再次修改了示例以尝试将复制构造函数设置为 constexpr 是否也能解决问题。确实如此。

Wandbox 上的生活演示。

【讨论】:

    【解决方案2】:

    你可以有一个参数化 constexpr 某种类型的函数 T 返回一个类型为 T 的值,T 是一个用户定义的类。简单例子:

    #include <iostream>
    
    struct A {
    private:
        int x;
    public:
        constexpr A(int x) : x(x) {};
        void print() {
            std::cout << x;
        }
    };
    
    constexpr A foo(int p) {
        A temp{ p };
        return temp;
    }
    
    int main() {
        A o = foo(123);
        o.print();
    }
    

    constexpr 函数的全部意义在于它的返回类型满足constant expression 的要求。

    【讨论】:

    • 不应该将构造函数声明为constexpr吗?
    • @CrisLuengo 确实如此。已更新。
    猜你喜欢
    • 1970-01-01
    • 2014-04-03
    • 2013-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    • 2015-12-21
    相关资源
    最近更新 更多