Pet*_*etr 20 c++ const move-semantics c++11
我有一个外部库,我无法修改.该库声明了一个模板函数,该函数由于某种原因返回const非引用对象:
template<class C>
const C foo();
Run Code Online (Sandbox Code Playgroud)
我有另一个外部库,我无法修改.该库声明了一个不可复制的类,并且只有非const对象的移动构造函数:
struct bar {
bar();
bar(const bar&)=delete;
bar(bar&&);
};
Run Code Online (Sandbox Code Playgroud)
现在我需要使用foo<bar>.一个简单的用法:
bar buz() {
return foo<bar>();
}
Run Code Online (Sandbox Code Playgroud)
失败了
Run Code Online (Sandbox Code Playgroud)main.cpp: In function 'bar buz()': main.cpp:13:21: error: use of deleted function 'bar::bar(const bar&)' return foo<bar>(); ^ main.cpp:8:5: note: declared here bar(const bar&)=delete; ^~~
这是有道理的,并没有简单的解决方法使代码编译.
但是,如果我添加一些更复杂的解决方法:
bar buz() {
return const_cast<bar&&>(std::move(foo<bar>()));
}
Run Code Online (Sandbox Code Playgroud)
它编译并且整个代码按预期工作(不仅是上面的简化示例,而且我的真实代码也是如此).
但是,它是安全的,还是我遇到了一些未定义的行为?有没有更好的解决方法?
我已阅读并理解有关返回的问题const从功能(1,2),以及常见的答案似乎是返回const对象在现代C++气馁,但我的问题是不是这件事,但我如何能解决该情况当外部库返回const对象时.
如果移动构造函数用于bar修改任何内容,则转换const将导致未定义的行为.你可以解决这个问题,而不会引入未定义的行为:
struct wrapped_bar {
mutable bar wrapped;
};
bar buz()
{
return foo<wrapped_bar>().wrapped;
}
Run Code Online (Sandbox Code Playgroud)
使wrapped成员变为可变意味着该成员是非const的,即使该wrapped_bar对象作为整体是const.根据foo()工作原理,您可能需要添加成员wrapped_bar以使其更像是一个工作bar.
从技术上讲,您正在将程序暴露给未定义的行为。由于声明了原始对象C(临时对象)const,因此对其进行常量转换和修改是非法的并且违反标准。(我假设,移动构造函数对移动对象进行了一些修改)。
话虽这么说,它可能适用于您的环境,但我没有看到更好的解决方法。