簡體   English   中英

為什么不重載分辨率選擇第一個函數?

[英]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;
}

並使用相同的額外! 在第二個。 這更具描述性,因為代碼很清楚它的作用。

實例

對於迭代器類型foodecltype(*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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM