1

我有一对这样定义的函数模板:

template<typename CollectionType>
Foo<CollectionType> f(const CollectionType& v)
{
   return Foo<CollectionType>(v); // copies v into a member variable
}

template<typename CollectionType>
Foo<CollectionType> f(CollectionType&& v)
{
   return Foo<CollectionType>(std::move(v)); // moves v into a member variable
}

如果我f如下调用:

std::vector<int> v;
f(v);

VC++ 编译器倾向于&&重载,显然是因为它的专用性较低。我希望const&在这种情况下调用重载——该&&版本适用于f(ReturnAVector()). 有没有办法在不手动指定模板参数的情况下实现这一点?

经过相当多的努力,我想出了这个:

template<typename CollectionType>
Foo<CollectionType> f(const CollectionType& v)
{
    return Foo<CollectionType>(v); // copies v into a member variable
}

template<typename CollectionType>
typename std::enable_if<std::is_rvalue_reference<CollectionType&&>::value,
    Foo<typename std::remove_reference<CollectionType>::type>>::type
f(CollectionType&& v)
{
    return Foo<CollectionType>(std::move(v)); // moves v into a member variable
}

但是哇;这真的是获得我所追求的最简单的方法吗?

4

2 回答 2

3

第二个重载总是完全匹配。所以实际上不需要第一个重载,它只会引起歧义。您应该转发论点,而不是移动。

template<typename CollectionType>
Foo<CollectionType> f(CollectionType&& v)
{
   return Foo<CollectionType>(std::forward<CollectionType>(v));
}

Scott Meyers 对此给出了很好的解释:http ://scottmeyers.blogspot.nl/2012/11/universal-references-in-c11-now-online.html

于 2014-09-19T17:36:05.303 回答
3

和:

std::vector<int> v;
f(v);

f(std::vector<int>&)这么叫

template<typename CollectionType>
Foo<CollectionType> f(CollectionType&& v)

是完全匹配(通用参考)CollectionTypestd::vector<int>&

template<typename CollectionType>
Foo<CollectionType> f(const CollectionType& v)

需要 const 提升。

一个可能的解决方案是添加一个非 const 版本:

template<typename CollectionType>
Foo<CollectionType> f(CollectionType& v)

或转发您的论点,例如:

template<typename CollectionType>
Foo<typename std::remove_reference<CollectionType>::type>
f(CollectionType&& v)
{
    return Foo<typename std::remove_reference<CollectionType>::type>(std::forward<CollectionType>(v));
}
于 2014-09-19T17:00:46.753 回答