Я хочу иметь функцию, которая проверяет определенные условия на основе заданной функции обратного вызова.
Считает этот код:
class Foo{
template <class ParamType>
struct IsGood
{
typedef bool (*Check)(typename const ParamType*, int other);
};
template< typename ParamType >
void DoSmth(IsGood<ParamType>::Check isGood, const ParamType* param){
//...
if(isGood(param, some_int_calculated_here)) doSmthElse();
}
То, что я хочу, это позвонить с:
bool checkEqualInt(int* i, int j){return *i==j;}
bool checkEqualFloat(float* i, float j){return *i==j;}
DoSmth(checkEqualInt, &i);
DoSmth(checkEqualFloat, &i_float);
(Все построенные примеры, чтобы показать проблему)
Компилятор не получит это и выдает мне ошибку C2664 «преобразование параметра 1 из bool (int *, int) в bool (ParamType, int) невозможно»
Я там решение без использования
template< typename ParamType, Check >
void DoSmth(Check isGood, const ParamType param)
Который пропускает необходимое объявление функции проверки?
Лучшим решением было бы получить заголовок IsGood () в самой функции.
Использование шаблона функтора решит ваши проблемы:
template< typename Functor, typename ParamType >
void DoSmth(Functor isGood, const ParamType param){
//...
if(isGood(param, some_int_calculated_here)) doSmthElse();
}
Теперь вы можете использовать любую функцию или объект функтора, который имеет совместимую подпись (не обязательно такую, которая принимает ParamType
и int
в качестве параметров). В противном случае вам нужно будет использовать функции с точной подписью.
Проблема в том, что первый аргумент вашей шаблонной функции не выводим:
template< typename ParamType >
void DoSmth(typename IsGood<ParamType>::Check isGood, const ParamType param)
// ^ ^^^^^^^^^^^^^^^^^^^^^^^^
// missing nested type! not deducible!
Простой вариант — развернуть подпись на месте (C ++ 03, C ++ 11):
template< typename ParamType >
void DoSmth(void (*isGood)(ParamType,int), const ParamType param)
// note: dropped 'const' that will be dropped anyway by the compiler
Или, если у вас есть C ++ 11, вы можете заменить IsGood<ParamType>::Check
по псевдониму шаблона:
template <typename T>
using IsGood = void (*)(T,int);
template< typename ParamType >
void DoSmth(IsGood<ParamType> isGood, const ParamType param)
Или, в качестве альтернативы, рефакторинг вашего кода для использования функтора, который сделает его более гибким, простым и, возможно, эффективным, поскольку компилятору будет проще встроить вызов:
template <typename P, typename T>
void DoSmth(P predicate, T param) {
if (predicate(param,somethingelse)) { ...
}