统一const T&和T&&重载

时间:2012-04-18 14:54:54

标签: c++ templates rvalue-reference move-semantics perfect-forwarding

我有以下两个函数模板重载:

template<typename T>
optional<T> some(const T& x)
{
    return optional<T>(x);
}

template<typename T>
typename std::enable_if<std::is_rvalue_reference<T&&>::value, optional<T> >::type
some(T&& x)
{
    return optional<T>(std::move(x));
}

我首次尝试通过完美转发统一过载失败:

template<typename T>
optional<T> some(T&& x)
{
    return optional<T>(std::forward<T>(x));
}

error: forming pointer to reference type 'const std::basic_string<char>&'

我的第二次尝试也是如此:

template<typename T>
optional<typename std::remove_reference<T>::type> some(T&& x)
{
    return optional<typename std::remove_reference<T>::type>(std::forward<T>(x));
}

error: no matching function for call to
'std::basic_string<char>::basic_string(gpa::optional<const std::basic_string<char> >)'

是否有一种简洁的方法来统一过载,或者我应该忍受它们?

2 个答案:

答案 0 :(得分:4)

我不熟悉您的optional,但您可能需要添加:

typename remove_const< ... >::type

remove_reference左右的两个地方。 (因为你的2重载解决方案的首次超载 - 我认为它通过了所有测试 - 在声明remove_const时有效地执行了optional<T>

答案 1 :(得分:1)

通常,执行此操作的最佳方法是按值获取对象,然后让调用者决定是复制还是移动它:

template<typename T>
optional<T> some(T x)
{
    return optional<T>(std::move(x));
}

如果调用者使用临时值调用它或者使用std::move值,则会移动它。否则就会被复制。

是的,这意味着您将进行一次额外的移动(如果移动与复制相同,则表示执行两次复制)。如果这对您来说是一个重大的性能问题,那么您将不得不使用两个重载实现。