0

Wie kann die richtige Funktionsüberladung im folgenden Fall richtig ausgewählt werden?Wie wähle ich die richtige Funktionsüberlastung aus?

#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

Parameteranzahl. – knivil

Antwort

3

Sie können die Mehrdeutigkeit des Prädikats selbst lösen, indem Sie ein Lambda verwenden;

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; 
} 

Es ist auch wichtig zu bedenken, dass das Nicht-Template der Template-Funktion vorgezogen wird.

Alternativ können Sie den Funktionszeiger (aber meiner Meinung nach dies ist umständlicher) werfen;

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

Demo.

Variationen der Zeigerausprägung umfassen das Eingeben des Funktionszeigertyps und dann das Abrufen einer lokalen Variablen, die auf die erforderliche Funktion zeigt;

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.


Auf der Materie, aus der Option besser ist, hängt es von der Komplexität des Codes außerhalb der Probe, dessen Standort (dh Code vs Dritten Code), das Volumen des mehrdeutigen Fehlers, das Prädikat selbst .

Angesichts der einfachen Bedingung wie im OP-Code könnte ein Lambda den Test selbst enthalten. Das Lambda ist in diesem Fall sehr einfach.

Wenn die Anzahl hoch ist, könnte die Version using mit einem höheren Gültigkeitsbereich (mit einer lokalen Variablen für die Zeigerkonvertierung) geeignet sein.

Wenn es ein "einmaliges" Problem ist, wäre die static_cast auch in Ordnung. Trotzdem sieht die Besetzung "fehl am Platz" aus.

Letztendlich ist es wahrscheinlich am meisten von persönlichen Vorlieben beeinflusst (oder Richtlinien, wenn Sie irgendwelche haben, die diese Situation abdecken).

Das Lambda kann auch mit moderneren Einsatz von auto&& und einigen variadic Argumente Liste, as seen in this answer in the linked question kombiniert werden. Es lohnt sich zu bedenken, dass diese modernen Techniken gut ineinandergreifen. Die meisten modernen Compiler optimieren auch das Lambda in diesem Fall, so dass es keine Kosten bei der Verwendung gibt (dies gilt für alle Optionen hier, da alle nur die Ambiguität auflösen).

Idealerweise sollte es anfangs nicht wirklich Abiguität geben, aber es passiert und wir müssen uns so gut wie möglich mit dem Kontext befassen, in dem wir es finden.

+0

Ich habe gerade die 'static_cast' Antwort eingegeben, +1, um sie hinzuzufügen. Dies wäre eine schlechte Verwendung eines Lambda, obwohl ich hoffen würde, dass der Compiler es eliminieren würde. –

+0

Dennoch sehe ich die Verwendung eines Lambda als vorzeitige Pessimierung. –