是否可以使用 lambda 初始化变量(删除复制 ctor 时)

Is it possible to initialize variable with lambda (when copy ctor is deleted)?

本文关键字:复制 删除 ctor 变量 可以使 lambda 初始化 是否      更新时间:2023-10-16

我有以下代码:

struct A {//<-- Third party library class
  A(){};
  A(const A&) = delete;
  void init(){};
  int i;
};

int f(){
  static A a = []{
    A res; 
    res.init(); 
    return res;
    }();
  return a.i;
}

现场观看:http://coliru.stacked-crooked.com/a/a5c5912bd79053c3

编译时会给出以下错误:

g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In lambda function:
main.cpp:12:12: error: use of deleted function 'A::A(const A&)'
     return res;
            ^~~
main.cpp:4:3: note: declared here
   A(const A&) = delete;
   ^

我知道我可以将其包装在另一个struct中并在该构造函数中初始化,但这似乎有些乏味。使用 c++17,我们是否有解决这个"问题"的"巧妙"方法?

任何解决方案都必须同样适用于函数中的静态变量

如果您的类不可移动,并且复制构造函数被删除/不可访问,那么您别无选择,只能返回对静态对象的引用或返回指针。 这是因为 C++17 的保证复制省略仅适用于 prvalues。 由于对象在 lambda 中具有名称,因此即使应用 NRVO,也必须能够将其移动或复制到返回对象中。

您可以使用

A& a = []() -> A& {
    static A res; 
    res.init(); 
    return res;
}();

auto a = []{
    auto res = std::make_unique<A>(); 
    res->init(); 
    return res;
}();

您可以在默认构造函数上调用init。然后,您可以在静态函数和静态成员函数上执行此操作。也可以在 prvalues 上使用复制省略号并提供类似 A res = []{ return A(); }(); .

#include <iostream>
struct A {//Third party library class
  constexpr A() :i{}
  { init(); };
  A(const A&) = delete;
  constexpr void init(){ i = 5; };
  int i;
};
struct A_User {
    static constexpr void A_print() {
        constexpr A res{};
        static_assert(res.i == 5);
    }
};
A& static_func() {
    static A res{};
    std::cout << "res static: " << res.i << "n";
    return res;
}
A res = []{ return A(); /* copy elided since this is prvalue */ }();
int main() {
    std::cout << "res global: " << res.i << "n";
    auto& static_A = static_func();
}