2014-01-13 4 views
1

Я хочу сделать функцию MapIf в классе Map. MapIf будет называться так:функция, которая получает указатель на функцию и указатель на класс?

void addThree(int& n) { 
    n += 3; 
} 

class startsWith { 
    char val; 

public: 

    startsWith(char v) : val(v) {}; 

    bool operator()(const std::string& str) { 
     return str.length() && char(str[0]) == val; 
    } 
}; 

int main(){ 
... 
    startsWith startWithB('B'); 

    Map<std::string, int> msi; 

    MapIf(msi, startWithB, addThree); 
    return 0; 
} 

Что бы декларация MapIf?

void MapIf(const Map& map, class condition, void (*function)(ValueType)); 

это нормально?

+0

Интересно, как вы узнали, как выглядит вызов функции, но не прототип функции. –

+0

Является ли Карта как в std :: map (ассоциативный контейнер) или как в map-reduce? (Выполните операцию над каждым элементом в последовательности). Может быть и здесь, поскольку вы ищете, имеет ли ключ предикат, а затем работает по его значению. – CashCow

ответ

1

После должен соответствовать ваш прототип.

template <typename Key, typename Value, typename Condition> 
void MapIf(const Map<Key, Value>& map, Condition condition, void (*function)(Value&)); 
+0

Да, если у вас есть сомнения, просто скопируйте все параметры и дайте компилятору выработать то, что вы на самом деле хотите ... В случае условия, хотя я согласен, что это должен быть шаблонный параметр. – CashCow

+0

Зачем вам шаблон каждого аргумента? Это было бы очень склонно к неудобным ошибкам; например функция может быть вызвана с чем угодно, но вы получите критические сообщения об ошибках, когда тело функции будет скомпилировано. –

+0

@ PeterR.Bloomfield: OP не предоставил 'Map',' ValueType'. Поэтому вместо использования волшебного шара я предоставляю правильный (неопределенный) ответ. Нет, у нас больше информации, я ограничиваю свой прототип. – Jarod42

0

Скорее

void MapIf(const Map& map, startsWith condition, void (*addThree)(int)); 
+0

MapIf - это жанр – user3036061

+2

Именование функции указатель 'addThree' запутан. Возможно, функция «MapIf» может использоваться с любым указателем функции, соответствующим правильной сигнатуре (т. Е. Не только пример «addThree» в вопросе). –

0

Это выглядит так, как вы хотите иметь несколько условий, и все условия function objects. Я могу предложить вам использовать std :: function для условия. В этом случае вы можете использовать этот класс и другие классы и другие функции и даже lambdas;

MapIf(Map<std::string, int>& map, std::function<bool(const std::string&)> condition, std::function<void(int&)> callback); 

в этом случае вы могли бы назвать эту функцию в этом способами:

MapIf(msi, startWithB, addThree); 

MapIf(msi, [](const string& str)->bool{return str.length() % 2 = 0}, addThree); 

MapIf(msi, startWithA, [](int& val){val-=2}); 

Вы можете использовать шаблоны, чтобы сделать его более универсальным, конечно.

+0

Зачем вы принимаете здесь объект 'std :: function'? Примите Functor через шаблон. Цель 'std :: function' заключается не в том, чтобы упростить чтение деклараций указателей функций, а в том, чтобы обеспечить стирание типа над вызываемыми объектами. Почти никогда не нужно раскрывать это вызывающему абоненту. – pmr

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