模板扣/重载决议有利于牛逼&&超过常量T&(Template deduction/o

2019-10-21 00:46发布

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

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
}

但是,哇; 这难道让我后最简单的方法?

Answer 1:

附:

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推广。

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

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));
}


Answer 2:

第二个重载总是完全匹配。 所以其实没有必要,第一过载,它只能引起歧义。 而不是移动的,你应该提出的论点。

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

斯科特迈尔斯给了这样一个优秀的解释: http://scottmeyers.blogspot.nl/2012/11/universal-references-in-c11-now-online.html



文章来源: Template deduction/overload resolution favors T&& over const T&