Как передать оператор в качестве аргумента функтора по умолчанию? - PullRequest
4 голосов
/ 02 ноября 2011

Для простоты, скажем, я хочу реализовать функцию, которая принимает два параметра и предикат, который проверяет равенство,

template<typename T, typename TCompare>
bool Eq(const T& a, const T& b, const TCompare& cmp) {
  return cmp(a, b);
}

но я также хочу, чтобы operator== предполагалось, если предикат не передан.

Я пробовал несколько разных подходов, но все привели к синтаксической ошибке или "operator ==" не определено. Я даже пытался заменить функцию Eq на

Тем не менее, я предполагаю, что то, что я хочу, возможно, так как большая часть STL поддерживает не передачу необязательного параметра TCompare (std :: sort, std :: set ...).

UPDATE : Благодаря предложению levis501, это лучший способ, который я нашел до сих пор:

template<typename T, typename TCompare>
bool Eq(const T& a, const T& b, const TCompare& cmp) {
  return cmp(a, b); // or some lengthy code
}

template<typename T>
bool Eq(const T& a, const T& b) {
  static std::equal_to<T> EqCmp;
  return Eq(a, b, EqCmp);
}

Итак, вам нужно создать оболочку, которая передает std :: equal_to или любой другой эквивалентный оператору функтор. По какой-то причине наличие его в качестве аргумента по умолчанию не компилируется при вызове функции без нее.

Ответы [ 3 ]

4 голосов
/ 02 ноября 2011
1 голос
/ 02 ноября 2011

Я не думаю, что что-то вроде следующего будет работать для вас:

#include <functional>

template<typename T, typename TCompare = std::equal_to<T>>
class Math {
public:
    static bool Eq(const T& a, const T& b) {
        TCompare cmp;

        return cmp(a, b);
    }
};

int _tmain(int argc, _TCHAR* argv[]) {
    Math<int>::Eq(1,1);

    return 0;
}

Параметры шаблона по умолчанию разрешены только для шаблонов классов (или, по крайней мере, так говорит MSVC 10)

1 голос
/ 02 ноября 2011

Вы можете перегружать функции, не так ли?

// Use the user-supplied TCompare.
template<typename T, typename TCompare> 
bool Eq(const T& a, const T& b, TCompare cmp) { 
  return cmp(a, b); 
} 

// Use op== for equality otherwise.
template<typename T> 
bool Eq(const T& a, const T& b) { 
  return a == b; 
} 

Если код вызывает Eq() с тремя аргументами, компилятор разрешит вызов первой перегрузки.Если код вызывает Eq() только с двумя аргументами, компилятору придется разрешить вторую перегрузку.

...