模板扣除/重载分辨率有利于T&&在const T&

时间:2014-09-19 16:46:38

标签: c++ templates universal-reference

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

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 ++编译器支持&&重载,显然是因为它是less specialized。我想在这种情况下调用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
}

但哇;得到我想要的东西真的是最简单的方法吗?

2 个答案:

答案 0 :(得分: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));
}

答案 1 :(得分: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