是否可以使用lambda初始化变量(删除副本ctor时)?

时间:2019-03-29 12:16:02

标签: c++ lambda initialization c++17

我有以下代码:

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中并在该构造函数中进行初始化,但这似乎有些乏味。 使用,我们是否有“整洁”的方式解决这个“问题”?

对于函数中的静态var,任何解决方案都必须同样有效

2 个答案:

答案 0 :(得分:4)

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

您可以使用

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

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

答案 1 :(得分:-1)

您可以在默认构造函数上调用init。然后,您可以在静态函数和静态成员函数上使用它。也可以在prvalue上使用复制省略,并提供类似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();
}