У меня есть функция более высокого порядка map
, которая похожа на STL for_each
и сопоставляет объект std::function
над vector
вещей.
template<class T, class U>
vector<U> map(function<U (T)> f, vector<T> xs) {
vector<U> ret;
for (auto &x: xs)
ret.push_back(f(x));
return ret;
}
Теперь я хочу, чтобы эта функция более высокого порядка принимала оба объекта типов function<int (const vector<T>&)>
и function<int (vector<T>)>
, как показано в прилагаемом минимальном примере.
Проблема заключается в том, что function<int (const vector<T>&)>
и function<int (vector<T>)>
кажутся конвертируемыми друг к другу (см. head
и head2
), но map
не будет принимать версию ссылок const function<int (const vector<int>&)>
(см. Q1
).
Можно указать map
принять версию ссылки const с явным преобразованием (Q2
), но это довольно громоздко.
Мне было интересно, можно ли вообще написать функцию deref
, которая удаляет константную ссылку из function<int (const vector<T>&)>
и возвращает function<int (vector<T>)>
?
(Если выше возможно, тогда мне не придется писать две идентичные перегрузки/реализации карты для const refs).
Спасибо.
#include <vector>
#include <functional>
using namespace std;
template<class T, class U>
vector<U> map(function<U (T)> f, vector<T> xs) {
vector<U> ret;
for (auto &x: xs)
ret.push_back(f(x));
return ret;
}
int main() {
vector<vector<int>> m;
function<int (const vector<int>&)> head = [](const vector<int>& a) {return a[0];};
function<int (const vector<int>&)> head1 = [](vector<int> a) {return a[0];}; //conversion OK
function<int (vector<int>)> head2 = [](const vector<int>& a) {return a[0];}; //conversion OK
map(head2,m); //OK
map(head,m); //Q1: problem line, implicit conversion NOT OK
map(function<int (vector<int>)>(head),m); //Q2: explicit conversion OK
map(deref(head),m); //Q3: ??How-to, deref takes a std::function f and returns a function with const ref removed from its signature
return 0;
}
--- EDIT ---
Меня особенно интересует подобная функция deref
или мета-функция, которая может удалить const ref из сигнатуры типа объекта std::function
, так что я могу как минимум сделать Q2
автоматически.
Я знаю, что, как правильно указывали @Brian и @Manu, использование std::function
для указания типов не является обычным, но мне интересно, что я спросил выше, даже выполнимо. Лично я думаю, что код с std::function
имеет большую ясность, учитывая, как в С# используются общие типы функций Func<T1, T2, T3, ...,Tn, Tresult>
. Это, если стоимость стирания типа допустима.
Я полностью согласен с тем, что С++ может выводить типы возвращаемых данных и давать сообщение об ошибке, если тип неверен. Возможно, это просто вопрос вкуса, и я бы предпочел записать его при написании сигнатур функций.