Перегрузка шаблонной функции, которая может различать нестатический метод-член и другие функции.

struct A // some class
{
void method(); // non-static member method
static void function(); // static member method
};
void function(); // global function
vector<A> vi; // any such `std` like container

Я хочу иметь функцию (скажем, Iterate()) который можно назвать ниже:

Iterate(vi, &A::method);  // (1)
Iterate(vi, &A::function); // (2a)
Iterate(vi, &function); // (2b)

(2a) и (2b) просто идентичны.

Сейчас Iterate() Прототип выглядит следующим образом для (1) и (2):

template<typename Container, typename Method>
void Iterate (Container &container, Method method); // for (1)

template<typename Container, typename Function>
void Iterate (Container &container, Function function); // for (2a), (2b)

Естественно, что оба абсолютно одинаковы, что приводит к ошибке компиляции.
Есть ли способ перегрузить / специализировать Iterate() в C ++ 03, который позволит обе функции сосуществовать?

3

Решение

Вы можете сделать одну функцию более конкретной, чем другую:

template<typename Container, typename Functor>
void Iterate (Container &container, Functor fun);

template<typename Container, typename R, typename ..Args>
void Iterate (Container &container, R (Container::value_type::*fun)(Args...));

Первый шаблон будет работать для обычных функций, объектов-функций и статических функций-членов, а второй — только для нестатических функций-членов.

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

template<typename Container, typename R>
void Iterate (Container &container, R (Container::value_type::*fun)());

template<typename Container, typename R, typename Arg>
void Iterate (Container &container, R (Container::value_type::*fun)(Arg));

template<typename Container, typename R, typename Arg1, typename Arg2>
void Iterate (Container &container, R (Container::value_type::*fun)(Arg1, Arg2));

//add more overloads to handle member functions
//that take 3 or more arguments

Конечно, если вам нужно реализовать их по-другому. Например, синтаксис для вызова функции-члена будет (obj.*fun)(a1,a2,a3); в то время как синтаксис вызова функтора просто fun(a1,a2,a2), Я не знаю, какие аргументы вы бы передали функции (член или функтор). Я предполагаю, что это не настоящий код, вы просто хотите изучить синтаксис.

Одним из важных моментов является то, что obj (из контейнера) есть не необходимо вызвать функтор, но вы можете передать его в качестве аргумента.

1

Другие решения

Других решений пока нет …