C ++, как передать метод в качестве аргумента шаблона - PullRequest
3 голосов
/ 11 апреля 2011

Предположим, у меня есть класс X:

class X {
    // ...
    size_t hash() const { return ...; }
};

Я хотел бы создать std::tr1::unordered_map<X, int, HashFn>, где я хочу пройти X::hash() как HashFn. Я знаю, что могу объявить свой собственный объект функтора. я так чувствую должен быть способ сделать это путем прямой передачи указателя на X::hash().

Есть?

Ответы [ 4 ]

2 голосов
/ 11 апреля 2011

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

#include <functional>

template<typename T, std::size_t (T::*HashFunc)() const = &T::hash>
struct hasher : std::unary_function<T, std::size_t>
{
    std::size_t operator ()(T const& t) const
    {
        return (t.*HashFunc)();
    }
};

Тогда вы можете создать unordered_map примерно так:

std::tr1::unordered_map<X, int, hasher<X> > m;
2 голосов
/ 11 апреля 2011

Нет, нет. Причина в том, что все, что используется в качестве вашего HashFn, должно принимать один аргумент, который является константной ссылкой на объект в контейнере. X::hash принимает единственный аргумент, который является постоянным указателем на объект в контейнере (указатель this является неявным первым аргументом в этом случае), поэтому использование этой функции само по себе невозможно .

Вы, вероятно, используете магию связывания, используя boost :: lambda и boost :: bind. Я не совсем уверен, как, но это будет выглядеть примерно так:

boost::bind(&X::hash, &_1);

Который создает объект функции, который будет вызывать X :: hash с указателем.

0 голосов
/ 11 апреля 2011

Вы не можете напрямую, но вы можете обернуть это. Самый простой способ сделать это - использовать boost::mem_fn() или стандартные эквиваленты, если ваш компилятор поддерживает их: tr1::mem_fn() (из TR1) или std::mem_fn() (из C ++ 11).

РЕДАКТИРОВАТЬ: На самом деле это не так просто. mem_fn() будет нормально работать для параметра функции, но так как его возвращаемый тип не указан, его трудно использовать в качестве параметра шаблона. Если у вас есть поддержка C ++ 11, вы можете использовать decltype, чтобы найти тип; в противном случае вам, вероятно, лучше написать свой собственный функциональный объект, как вы упомянули.

0 голосов
/ 11 апреля 2011
size_t hash() const { return ...;}

Функция, которая вычисляет значение хеш-функции, принимает один параметр типа Key, который не принимает ваша функция. Следовательно, его подпись неверна.

Поскольку вы хотите реализовать функцию, а не функтор, вот как это должно быть сделано:

size_t hash(const KeyType &key) 
{
    return /*calculate hash and return it*/;
}

Сделайте его static функцией-членом и передайте его как X::hash или сделайте его свободной функцией, это ваш выбор.

...