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

Вы можете устранить двусмысленность предиката самостоятельно, используя лямбда;

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.


По вопросу, какой вариант лучше, это зависит от сложности коды вне образца, их расположение (т.е. вашего кода против кода третьей стороны), объем неоднозначных ошибок, сам предикат ,

Учитывая простое условие, как в OP-коде, лямбда может содержать сам тест. В этом случае лямбда очень проста.

Если счетчик высок, версия using в более высокой области (с локальной переменной для преобразования указателя) может быть подходящей.

Если это вопрос «один раз», то static_cast будет также прекрасным. Хотя бросок выглядит «неуместным».

В конечном итоге это, вероятно, больше всего зависит от личных предпочтений (или рекомендаций, если у вас есть такие, которые охватывают эту ситуацию).

Лямбда также может быть объединена с более современным использованием auto&& и некоторыми вариационными аргументами, as seen in this answer in the linked question. Стоит иметь в виду, что эти современные технологии хорошо согласуются. Большинство современных компиляторов также оптимизируют лямбда в этом случае, поэтому нет никаких затрат на его использование (это применимо ко всем вариантам здесь, там все просто устраняются двусмысленность).

В идеале на самом деле на самом деле не должно быть непоследовательности, но это происходит, и нам нужно иметь дело с ним наиболее подходящим способом, который мы можем в контексте, который мы находим.

+0

Я просто набрал ответ 'static_cast', +1 для его добавления. Это было бы плохое использование лямбда, хотя я бы надеялся, что компилятор его устранит. –

+0

Тем не менее, я рассматриваю использование лямбды как преждевременную пессимизацию. –

Смежные вопросы