【发布时间】:2014-03-26 14:59:28
【问题描述】:
以下是否是 Scope Guard 的惯用 C++11 实现,它在范围退出时恢复值?
template<typename T>
class ValueScopeGuard
{
public:
template<typename U>
ValueScopeGuard(T& value, U&& newValue):
_valuePtr(&value),
_oldValue(std::forward<U>(newValue))
{
using std::swap;
swap(*_valuePtr, _oldValue);
}
~ValueScopeGuard()
{
if(_valuePtr)
{
using std::swap;
swap(*_valuePtr, _oldValue);
}
}
// Copy
ValueScopeGuard(ValueScopeGuard const& other) = delete;
ValueScopeGuard& operator=(ValueScopeGuard const& other) = delete;
// Move
ValueScopeGuard(ValueScopeGuard&& other):
_valuePtr(nullptr)
{
swap(*this, other);
}
ValueScopeGuard& operator=(ValueScopeGuard&& other)
{
ValueScopeGuard(std::move(other)).swap(*this);
return *this;
}
private:
T* _valuePtr;
T _oldValue;
friend void swap(ValueScopeGuard& lhs, ValueScopeGuard& rhs)
{
using std::swap;
swap(lhs._valuePtr, rhs._valuePtr);
swap(lhs._oldValue, rhs._oldValue);
}
};
template<typename T, typename U>
ValueScopeGuard<T> makeValueScopeGuard(T& value, U&& newValue)
{
return {value, std::forward<U>(newValue)};
}
它可以用来临时改变一个值,如下所示:
int main(int argc, char* argv[])
{
// Value Type
int i = 0;
{
auto guard = makeValueScopeGuard(i, 1);
std::cout << i << std::endl; // 1
}
std::cout << i << std::endl; // 0
// Movable Type
std::unique_ptr<int> a{new int(0)};
{
auto guard = makeValueScopeGuard(a, std::unique_ptr<int>{new int(1)});
std::cout << *a << std::endl; // 1
}
std::cout << *a << std::endl; // 0
return 0;
}
这样的简单实用程序是否已经在某个库中实现了?我查看了 Boost.ScopeExit,但它的预期用途似乎不同且更复杂。
【问题讨论】:
-
对构造函数使用'template
ValueScopeGuard(T& value, U&& newValue)'。同样,为“makeValueScopeGuard”使用单独的模板类型。这将允许完美转发工作并允许左值和右值。 -
@John5342:啊,我知道现在发生了什么!
T&&不是“通用”引用,因为T是从第一个参数推导出来的。已纳入建议。
标签: c++11 move-semantics rvalue-reference