我有以下代码:
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,我们是否有“整洁”的方式解决这个“问题”?
对于函数中的静态var,任何解决方案都必须同样有效
答案 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();
}