“перегрузка” шаблон функции, основанной на функции оператора объекта() подпись


Рассмотрим пример шаблона функции, которая принимает ссылку на функцию в качестве первого аргумента. Она перегружена на основе сигнатуры функции первого аргумента. Тело каждой перегрузки для 1-й аргумент функции, необходимые для его подписания.

template<typename T>struct MapTtoT { typedef T (type)(const T); };template<typename T>std::vector<T> map_vec(        const typename MapTtoT<T>::type& fnc,        const std::vector<T>& source){    std::vector<T> dest;    dest.reserve(source.size());    for (const auto i : source)    {        dest.emplace_back(fnc(i));    }    return dest;}template<typename T>struct MapTandVectoT { typedef T (type)(const T, const std::vector<T>&); };template<typename T>std::vector<T> map_vec(        const typename MapTandVectoT<T>::type& fnc,        const std::vector<T>& source){    std::vector<T> dest;    dest.reserve(source.size());    for (const auto i : source)    {        dest.emplace_back(fnc(i, source));    }    return dest;}

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

int foo(const int x);int bar(const int x, const std::vector<int>& v);

И делать это прозрачно:

const auto a = map_vec(foo, v);const auto b = map_vec(bar, v);

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

class AddNum{public:    AddNum(const int num) : num_(num) {}    int operator()(const int x) const    {        return x + num_;    }private:    const int num_;};class AddNumMulSize{public:    AddNumMulSize(const int num) : num_(num) {}    int operator()(const int x, const std::vector<int>& v) const    {        return (x + num_) * v.size();    }private:    const int num_;};

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

В частности, я хочу, чтобы скомпилировать:

const AddNum add2(2);const auto c = map_vec(add2, v);const AddNumMulSize add2mulsz(2);const auto d = map_vec(add2mulsz, v);

Сообщение об ошибке, что Clang дает вполне понятно и соответствует тому, что вы ожидаете.

error: no matching function for call to 'map_vec'

candidate function [with T = int] not viable: no known conversion from 'const AddNum' to 'typename MapTtoT::type &' (aka 'int (&)(const int)') for 1st argument

Update:

С 98 версии этот вопрос

“Overload” function template based on function object operator() signature in C++98