2014-03-28 4 views
9

Я хотел бы сделать функцию с параметром, который принимает значение std :: больше <int> или std :: less <int> как аргумент. Тем не менее, я придерживаюсь синтаксиса параметра.Параметр для использования std :: больше или std :: less как аргумент

Это формат я пробовал:

myFunction(int a, int b, bool *comp(int, int)) { … } 
… 
std::greater<int> bigger; 
myFunction(2, 3, bigger); 

Это не работает *, хотя, и я подозреваю, что третий параметр просто совершенно неправильно. Что это должно быть на самом деле?

* не может преобразовать 'станд :: больше' к «BOOL * (*) (Int, Int)

+2

pass 'std :: больше ()' вместо –

+0

Спасибо. Я обновил свой вопрос, чтобы передать экземпляр большего, а не класс. Ошибка такая же; В первый раз я просто не копировал свой код. Виноват. – Qaz

+1

Кстати, ваш параметр является функцией (преобразуется в указатель функции на прицел в этом контексте), беря два 'int' и возвращая 'bool *'. – chris

ответ

10

Функции, принимающие компаратор, как правило, реализуется с помощью шаблонов:

template <typename Comparator> 
myFunction(int a, int b, Comparator comp) { … } 

но вы также можете использовать std::function для его реализации:

myFunction(int a, int b, std::function<bool (int, int)>) { … } 

Первая версия предоставляет код в заголовке, но обычно работает лучше. Что касается второй версии, вы можете скрыть реализацию в файле .cpp, , но вы потеряете некоторую производительность из-за невозможности встроить вызовы компаратора .

2

Использование шаблона:

template<class Callable> 
myFunction(int a, int b, Callable f); 
7

Таким образом, уловка заключается в том, что std::less и std::greater являются фактически объектами функции без гражданства, которые могут быть построены тривиально. Но они не поддерживают кастинг для указателя функции.

Эффективные варианты либо (A) принимают компаратор с помощью template аргумента и реализовать код в заголовок:

template<typename C> void myFunc(int a, int b, C comp) 

, который означает, что вы должны реализовать его в файле заголовка, или (B) тип стереть объект функции через std::function< bool(int, int) >: (?! возможно значительные профиль)

void myFunc(int a, int b, std::function< bool(int, int) > comp) 

, который имеет некоторые затраты (распределение кучи избежать с помощью небольшой оптимизации объекта для лица без станда меньше/больше, но это, как правило, стоит virtual вызов функции независимо, что также может блокировать вложение).

Или (C) написать код, который позволяет принимать лица без функтора и превратить его в функцию указателя:

template<typename T> 
using Type = T; 
template<typename StatelessFunctor> 
struct function_ptr_of_stateless_t { 
    template<typename R, typename... Args> 
    operator Type<R(Args...)>*() const { 
    return [](Args... args)->R { 
    return StatelessFunctor()(std::forward<Args>(args)...); 
    }; 
    } 
}; 
template<typename StatelessFunctor> 
function_ptr_of_stateless_t<StatelessFunctor> as_function_ptr() { 
    return {}; 
} 

bool myFunction(int a, int b, bool(*comp)(int, int)) { return comp(a,b); } 
int main() { 
    std::cout << myFunction(3,7, as_function_ptr<std::less<int>>()) << "\n"; 
} 

где template функция as_function_ptr принимает тип вашего лица без функтора и создает выбросить тип, который позволяет использовать его для любого типа совместимого типа функции.

Это скромно меньше накладные расходы, чем std::function решения, как вызов через указатель на функцию, как правило, быстрее, чем по методу virtual, а кроме того некоторые компиляторы (например, GCC) вполне приличные на функцию встраивания указателей, даже один блок компиляции к другому.

В качестве бонуса, в C++ 14 вы можете использовать:

int main() { 
    std::cout << myFunction(3,7, as_function_ptr<std::less<>>()) << "\n"; 
} 

и он все еще работает довольно оптимально.

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

  • Нет связанных вопросов^_^