шаблонный оператор () перегружает C ++ - PullRequest
8 голосов
/ 19 ноября 2009

кто-то уже задавал этот вопрос, но ветка закончилась тем, что исходный вопрос не получил ответа.

предположим, у вас есть это:

template<size_t i, class f_type>
void call_with_i(f_type f);

functor_type это либо:

a) структура с методом, который имеет следующую подпись:

template<size_t i> operator()() const;

или, б) функцию, которая выглядит следующим образом:

template<size_t i> foo();

Я хочу, чтобы call_with_i <42> (foo) был эквивалентен "foo <42> ()", но я не могу понять правильный синтаксис, чтобы это произошло. Я был бы удовлетворен решением, которое просто (а) , но (а) + (б) было бы здорово . Я уже пробовал эти синтаксисы:

f< i >(); // doesn't work
f()< i >; // doesn't work
f.operator< i >(); // doesn't work
f.operator()< i >; // doesn't work
f.operator()< i >(); // works on msvc, but doesn't work on gcc. 

Как вы вызываете operator () с явными аргументами шаблона? Есть ли способ вызвать его так, чтобы тот же синтаксис также вызывал шаблонную свободную функцию?

p.s. Если вам интересно, для чего я это использую, то это потому, что я пишу функцию repeat_to, где repeat_to <10> (f) вызывает f (0), а затем f (1) ... f (10). Я использую это, чтобы перебрать несколько векторов boost :: fusion параллельно по индексу. да, я мог бы использовать итераторы или я мог бы просто использовать именованную функцию-член, но я все еще хочу знать ответ.

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

Ответы [ 3 ]

13 голосов
/ 19 ноября 2009

Шаблон элемента является зависимым именем, поскольку его семантика зависит от типа f_type. Это означает, что вы должны поставить «шаблон» перед его именем (чтобы устранить неоднозначность использования токена «меньше»), подобно тому, как вы должны поставить typename перед зависимыми квалифицированными именами:

template<size_t i, class f_type>
void call_with_i(f_type f) {
  f.template operator()<i>();
  // f.template foo<i>();
}

В качестве обходного пути вы можете использовать вспомогательный тип:

template<size_t N> struct size_t_ { }; // or boost::mpl::int_

template<size_t i, class f_type>
void call_with_i(f_type f) {
  f(size_t_<i>());
}

Теперь вы можете определить ваш operator() следующим образом:

template<size_t i> void operator()(size_t_<i>) const {
  // i was deduced automatically by the function argument. 
}

Это удобно для шаблонных конструкторов, для которых вы не можете сделать f_type()<i>() или что-то еще. В этом случае будет иметь , подлежащую вычету.

1 голос
/ 19 ноября 2009

В случае, подобном вашему, я бы использовал boost :: function в качестве типа функтора. Затем вы можете передавать как функциональные объекты, так и указатели на функции, сохраняя один и тот же интерфейс.

0 голосов
/ 19 ноября 2009
#include <iostream>

template<size_t i, class f_type> void call_with_i(f_type f);

struct A {

    template < size_t i >
    void operator()() const {
        /* no link err in demo */
    }

    template < size_t i >
    void foo() {
        /* no link err in demo */
    }
};

int main(int argc, char * const argv[]) {
    A f;

    enum { Constant = 42 };

    f.operator()<Constant>();
    f.foo<Constant>();

    return 0;
}

Есть ли способ вызвать его так, чтобы тот же синтаксис также вызывал шаблонную свободную функцию?

Вы можете уточнить? (псевдокод или что-то)

...