3

假设我们有一个嵌入另一个参数的类,它必须支持复制和移动。让我们假设——在某些情况下——需要以某种方式找出内在价值。

一种典型的方法可以是这样的:

template<class T>
class wrapper
{
public:
    wrapper() :val() {}
    wrapper(T s) :val(std::move(s)) {}

    wrapper(const wrapper& s) :val(s.val) {}
    wrapper(wrapper&& s) :val(std::move(s.val)) {}
    wrapper& operator=(wrapper s) { val = std::move(s.val); return *this; }

    T value() const { return val; }
private:
    T val;
};

这不是唯一的方法,可能不需要明确复制和移动,但让它们成为。

另一点是:假设T-in ceratin instances- 本身就是一个复制/可移动类。当然,wrapper::value()返回 T 的副本。

现在假设返回的 T 必须作为参数进入另一个调用,并且包含的​​包装器是临时的。

更简单的模拟是

calledfn(wrapper<T>(someT).value());

再说一遍:以这种方式完成是毫无头绪的,但更复杂的情况需要这个微不足道的工作。

从理论上讲,我们可以承认val从它的临时包装器中移开以将其提供给调用者,但是...什么签名应该具有该value()方法,以便它在临时时wrapper<T>被绑定,但在不是临时时不被绑定,为此value() const应该是首选?

4

1 回答 1

6

在 C++11 中,您可以在this-pointer 是否为右值时重载方法:

T value() &&; //Will only be called if the object is a mutable rvalue
T value() const &; //Will only be called if the object is an lvalue

请注意,根据 13.1.2 [over.load]标准,如果任何重载具有引用说明符(左值或右值)都必须得到一个。所以非临时情况的重载必须是const &. 我不完全确定这是否会绑定到 const r 值,因此您可能需要const &&重载来捕获这种情况。

我不知道编译器对此功能的支持,所以如果还没有支持,这可能有点理论上的。在这种情况下,您可以通过创建一个move_value方法并使用一个分派到正确方法的自由函数来解决问题:

template<class T> class wrapper {
    ...    
    T value() const;
    T move_value();    
};
template<typename T> T value(wrapper<T>&& self) { return std::move(self.move_value(); }
template<typename T> T value(const wrapper<T>& self) { return std::move(self.value(); }
于 2012-06-28T13:04:41.403 回答