[英]Overload resolution for two functions taking parameter packs
請考慮以下兩個重載:
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參數包 )
通用參考矢量參數也綁定到左值參考 那么為什么只有參數包的重載在這種情況下受到青睞呢? 更新:請參閱接受的答案,假設向量參數是通用/轉發引用是錯誤的。
通用參考矢量參數也綁定到左值參考
不,這不是一個普遍的參考 。
4)如果P是對cv非限定模板參數的右值引用(所謂的“轉發引用”),並且相應的函數調用參數是左值,則使用對A的類型左值引用代替A進行推導(注意:這是std :: forward動作的基礎注意:在類模板推導中 , 類模板的模板參數永遠不是轉發引用(因為C ++ 17)):
因此對於
template<typename T, typename ...Args>
void f(std::vector<T>&& v, Args&& ...args)
請注意, v
不是模板參數T
的右值引用,而是std::vector<T>
。 所以v
是“只是”一個右值引用,然后不能綁定到左值。
正如接受的答案所解釋的那樣:
該向量不被視為轉發參考(又稱通用參考)。
(編譯器知道它是一個向量,因此這部分沒有模板引用推論,這意味着雙符號 - && - 被視為對未知類型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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.