У меня есть метод как это
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, T (f)(T,U))
{
map<T,U> new;
for(auto it = old.begin(); it != old.end(); ++it)
{
new[it->first] = f(it->first,it->second);
}
return new;
}
и идея состоит в том, что Вы назвали бы его как это
BOOST_AUTO_TEST_CASE(MapMapValues_basic)
{
map<int,int> test;
test[1] = 1;
map<int,int> transformedMap = VlcFunctional::mapMapValues(test,
[&](int key, int value) -> int
{
return key + 1;
}
);
}
Однако я получаю ошибку: никакой экземпляр шаблона функции "VlcFunctional:: mapMapValues" соответствует типам аргумента списка аргументов: (станд.:: карта, станд.:: средство выделения>>, __ lambda1)
Какая-либо идея, что я делаю неправильно? Visual Studio 2008 и компилятор Intel C ++ 11.1
Ваша функция ожидает указатель на функцию, а не лямбду.
В C ++, как правило, существует 3 типа «вызываемых объектов».
Если вы хотите иметь возможность использовать все это в интерфейсе вашей функции, вы можете использовать std :: function
:
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, std::function<T(T, U)> f)
{
...
}
Это позволит вызывать функцию с использованием любого из трех типы вызываемых объектов выше. Однако плата за это удобство заключается в небольших накладных расходах на вызовы функции (обычно проверка нулевого указателя, затем вызов через указатель функции). Это означает, что функция почти наверняка не встроена (за исключением, возможно, расширенного WPO / LTO ).
В качестве альтернативы, вы можете добавить дополнительный параметр шаблона, чтобы принять произвольный тип для второго параметра. Это будет более эффективно, но вы потеряете безопасность типов для используемой функции и может привести к еще большему раздутию кода.
template<typename T, typename U, typename F>
map<T,U> mapMapValues(map<T,U> old, F f)
Объявление типа вашего параметра T (f) (T, U)
относится к свободной функции типа, принимающей T
и U
и возвращающей Т
'. Вы не можете передать ему лямбду, объект функции или что-то еще, кроме фактической функции с этой подписью.
Вы можете решить эту проблему, изменив тип параметра на std :: function
следующим образом:
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, std::function<T(T,U)>)
{
}
В качестве альтернативы вы можете объявить тип функции как шаблон аргумент вроде этого:
template<typename T, typename U, typename Fn>
map<T,U> mapMapValues(map<T,U> old, Fn fn)
{
fn(...);
}
Лямбда-выражения с пустым списком захвата должны распадаться на указатели функций, согласно n3052 . Однако кажется, что эта функция не реализована в VC ++ и лишь частично в g ++, см. Мой вопрос SO .