【问题标题】:unifying const T& and T&& overloads统一 const T& 和 T&& 重载
【发布时间】:2012-04-30 00:34:47
【问题描述】:

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

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> >)'

有没有一种干净的方法来统一重载,还是我应该忍受它们?

【问题讨论】:

  • 您应该提供optional&lt;&gt; 的定义。
  • 它基本上是boost::optional的玩具克隆。
  • ...但问题仍然存在,您能提供定义吗?我感觉问题出在optional 的接口上(即完美转发是some 的解决方案,您可能需要调整它以适应optional

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


【解决方案1】:

我不熟悉你的optional,但也许你需要补充:

typename remove_const< ... >::type

在您的remove_reference 周围有两个地方。 (因为您的 2-overload 解决方案的第一次重载 - 我假设它通过了所有测试 - 在声明 optional&lt;T&gt; 时有效地执行 remove_const)。

【讨论】:

  • 为了安全起见不应该是remove_cv吗?
  • 如果这是我们想要的。当前的 2-overload 解决方案只是拒绝 volatile 限定的左值。如果没有完整的代码示例,我很难说出需要什么。
【解决方案2】:

一般来说,最好的方法是按值获取对象,让调用者决定是复制还是移动它:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多