0

在以下情況下選擇正確的功能過載的正確方法是什麼?如何選擇正確的功能過載?

#include <iostream> 
#include <algorithm> 

/** the correct overload **/ 
bool predicate(const char& c) 
{ 
    return c == '0'; 
} 

/** the wrong overload **/ 
template< typename CharType >  
bool predicate(const CharType& c, int some_other_parameters) 
{ 
    return c == '0'; 
} 

std::string 
process_string(const std::string& str) 
{ 
    std::string result; 
    std::copy_if(str.begin(), 
        str.end(), 
        std::back_inserter(result), 
        predicate); 

    return result; 
} 

int main() 
{ 
    std::cout << process_string("AK0NNDK0ASDAS0") << std::endl; 
    return 0; 
} 
+0

參數計數。 – knivil

回答

3

您可以使用lambda自己解析謂詞歧義;

std::string 
process_string(const std::string& str) 
{ 
    std::string result; 
    std::copy_if(str.begin(), 
        str.end(), 
        std::back_inserter(result), 
        [](char const& c) { return predicate(c); }); 
    //   ^^ use the lambda to call the correct overload 

    return result; 
} 

請務必記住,非模板將優於模板函數。或者,你可以強制轉換函數指針(但我認爲這比較麻煩);

std::copy_if(str.begin(), 
       str.end(), 
       std::back_inserter(result), 
       static_cast<bool(*)(const char&)>(&predicate)); 

Demo

指針轉換的變體包括鍵入函數指針類型,然後獲取指向所需函數的局部變量;

using predicate_t = bool(*)(const char&); 
predicate_t my_predicate = &predicate; 
std::copy_if(str.begin(), 
       str.end(), 
       std::back_inserter(result), 
       my_predicate); 

Demo


在哪個選項是更好的事情,這取決於樣本外的代碼的複雜性,他們的位置(即代碼VS第三方代碼),曖昧的錯誤的量,謂詞本身。

考慮到OP代碼中的簡單條件,lambda可以包含測試本身。 lambda在這種情況下非常簡單。

如果計數較高,則較高範圍的using版本(使用指針轉換的局部變量)可能是合適的。

如果是「一次性」問題,那麼static_cast也不錯。雖然演員看起來「不合適」。

最終,它最可能受個人喜好影響最大(或指導方針,如果你有任何涵蓋這種情況)。

該lambda也可以結合更現代的使用auto&&和一些可變參數列表as seen in this answer in the linked question。值得銘記的是,這些現代技術很好地吻合。大多數現代編譯器也對這種情況下的lambda表示樂觀,所以沒有使用它的代價(這適用於這裏的所有選項,這只是解決了歧義)。

理想情況下,開始時應該沒有真正的含糊之處,但這種情況發生了,我們需要以我們在上下文中找到的最合適的方式來處理它。

+0

我只是輸入'static_cast'的答案,+1來添加它。這將是一個不好的lambda使用,儘管我希望編譯器能夠消除它。 –

+0

無論如何,我認爲使用拉姆達作爲過早的悲觀化。 –