如果我们有一个带有非显式构造函数的不可移动的非可复制类,我们可以返回它并使用如下(在C++ 11中):
#include <iostream>
class NonCop
{
public:
/*non explicit*/ NonCop(int a, int b) : number(a + b) {}
NonCop(const NonCop&) = delete;
int number;
};
NonCop get_non_cop()
{
return {1, 2};
}
int main()
{
NonCop &&nc = get_non_cop();
std::cout << "three: " << nc.number << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果构造函数是显式的,则它不起作用.有没有任何方法在C++ 11/C++ 14中执行此操作而不进行任何修改NonCop?
目前我正在使用从NonCop派生的解决方法,使用"deexplicits"构造函数的包装器,但它看起来并不漂亮.
不,这是不可能的.在没有隐式移动或复制(编译器肯定会忽略)的情况下从C++ 11或14中的函数返回时,没有机制可以调用显式构造函数.
在C++ 17中,您只需输入return NonCop(1,2);,由于"保证省略",它将不再需要移动或复制构造函数.
但这是C++,所以是的,我可以让您的代码无需额外开销.通过作弊,并返回不同的类型.
template<class T>
struct implicit_construct:T {
template<class...Ts>
implicit_construct(Ts&&...ts):
T(std::forward<Ts>(ts)...) // note: this is an EXPLICIT construction
{}
};
implicit_construct<NonCop> get_non_cop()
{
return {1, 2};
}
Run Code Online (Sandbox Code Playgroud)
实例.
一个implicit_construct<NonCop>从派生NonCop,所以你可以存储在一个返回值NonCop&&.
如果你是NonCop自己写的,那么我要做的就是添加:
struct explicit_construct_t {};
// ...
struct NonCop {
// ...
template<class...Ts>
NonCop( explicit_construct_t, Ts&&...ts ):
NonCop( std::forward<Ts>(ts)... )
{}
// ...
};
Run Code Online (Sandbox Code Playgroud)
这意味着您可以通过在其前面添加一个explicit_construct_t隐式调用它来调用显式构造函数:
NonCop get_non_cop() {
return {explicit_construct_t{}, 1, 2};
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,在这种情况下,您无法返回临时对象,因为在按值返回表达式中,编译器要求对象的复制构造函数可访问,即使该对象最终将被复制删除。但是,您可以返回一个std::unique_ptr而不是具体的对象。
std::unique_ptr<NonCop> get_non_cop() {
return std::make_unique<NonCop>(1, 2);
}
Run Code Online (Sandbox Code Playgroud)