[英]Why doesn't overload resolution pick the first function?
在下面的程序中,兩個函數調用都打印“非整數過載”,即使我有一個enable_if
語句,只將函數限制為整數容器類型。 這是為什么?
#include <iostream>
#include <vector>
#include <type_traits>
template<bool B, typename V = void>
using enable_if = typename std::enable_if<B, V>::type;
template<typename ForwardIt>
auto f(ForwardIt first, ForwardIt)
-> enable_if<std::is_integral<decltype(*first)>{}>
{
std::cout << "Integral container type" << std::endl;
}
template<typename ForwardIt>
void f(ForwardIt, ForwardIt)
{
std::cout << "Non-integral container type" << std::endl;
}
int main()
{
struct X { };
std::vector<int> iv;
std::vector<X> xv;
f(iv.begin(), iv.end()); // "Non-integral container type"
f(xv.begin(), xv.end()); // "Non-integral container type"
}
我甚至嘗試在第二次重載時使用enable_if<!std::is_integral<...>>
但無濟於事。
另一個答案已經解釋了這個問題,但我認為有一個更好的解決方案。
如果要提取迭代器類型指向的類型,則應使用iterator_traits
。 在您的代碼中,將第一個重載更改為:
template<typename ForwardIt>
auto f(ForwardIt first, ForwardIt)
-> enable_if<std::is_integral<typename std::iterator_traits<ForwardIt>::value_type>{}>
{
std::cout << "Integral container type" << std::endl;
}
並使用相同的額外!
在第二個。 這更具描述性,因為代碼很清楚它的作用。
對於迭代器類型foo
, decltype(*foo)
將是foo::value_type&
。 參考類型絕對不是一個整體。 在使用std::is_integral
trait評估類型之前,您需要刪除引用(以及可能的cv資格,IIRC),這可以使用std::decay
轉換類型特征輕松完成:
template<bool B, typename V = void>
using enable_if = typename std::enable_if<B, V>::type;
template<typename T>
using decay = typename std::decay<T>::type;
template<typename ForwardIt>
auto f(ForwardIt first, ForwardIt)
-> enable_if<std::is_integral<decay<decltype(*first)>>{}>
{
std::cout << "Integral container type" << std::endl;
}
這將導致您的其他重載模糊,因為兩者現在都匹配。 您需要按照OP中的建議約束第二個重載。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.