请考虑以下两个重载:
template<typename T, typename ...Args>
void f(std::vector<T>&& v, Args&& ...args)
{
std::cout << "f taking a vector + parameter pack\n";
}
template<typename ...Args>
void f(Args&& ...args)
{
std::cout << "f taking a parameter pack\n";
}
现在,对于以下片段,选择了预期的重载:
std::vector<int> v{1, 2, 3};
f(std::move(v), 3.0);
(输出: f采用向量+参数包)
对于以下情况,选择第二个重载:
std::vector<int> v{1, 2, 3};
f(v, 3.0);
(输出: f参加参数包)
通用引用向量参数也绑定到左值引用,那么为什么在这种情况下仅使用参数包的重载是有利的呢? 更新:查看接受的答案,假设vector参数是通用/转发引用是错误的。
答案 0 :(得分:7)
通用参考向量参数也绑定到左值参考
不,它不是universal reference。
4)如果 P 是对cv-nonqualified模板参数的右值引用(所谓的&#34;转发引用&#34;),并且相应的函数调用参数是左值,使用 A 的类型左值引用代替 A 进行扣除(注意:这是std::forward操作的基础注意:在{{3 ,类模板的模板参数永远不是转发引用(因为C ++ 17)):
所以
template<typename T, typename ...Args>
void f(std::vector<T>&& v, Args&& ...args)
请注意,v
不是模板参数T
的右值参考,而是std::vector<T>
。所以v
是&#34;只是&#34;一个右值参考,然后不能绑定到左值。
答案 1 :(得分:2)
正如接受的答案所解释的那样:
该向量不被视为转发参考(又名通用参考)。
(编译器知道它是一个向量,因此这部分没有模板参考推论,这意味着双符号 - &amp;&amp; - 被视为对向量的右值引用未知类型T)。
如果您希望将矢量作为转发参考传递,您可以执行以下操作:
template<typename T> struct is_vector : public std::false_type {};
template<typename T, typename A>
struct is_vector<std::vector<T, A>> : public std::true_type {};
// [1] the special case
// the vector becomes now just V and acts as Forwarding Reference
// the enable_if ensures that we deal with V that is a vector
template<typename V, typename ...Args>
typename std::enable_if<
is_vector<std::remove_const_t<std::remove_reference_t<V>>>::value
>::type
f(V&& v, Args&& ...args) {
std::cout << "f taking a vector + parameter pack\n";
}
// [2] the generic case
template<typename ...Args>
void f(Args&& ...args) {
std::cout << "f taking a parameter pack\n";
}
int main() {
// all cases below go to the 1st overload
std::vector<int> v1{1, 2, 3};
f(v1, 3);
const std::vector<int> v2{1, 2, 3};
f(v2, 3);
f(std::vector<int>{1, 2, 3}, 3);
// this goes to the 2nd overload
std::array<int, 3> a{1, 2, 3};
f(a, 3);
}