J'ai une méthode comme celle-ci
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;
}
et l'idée est que vous l'appelez comme ça
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;
}
);
}
Cependant, j'ai l'erreur: aucune instance du modèle de fonction "VlcFunctional :: mapMapValues" ne correspond aux types d'arguments de la liste d'arguments: (std :: map, std :: allocator >>, __lambda1)
Une idée de ce que je fais mal? Compilateur Visual Studio 2008 et Intel C++ 11.1
Votre fonction attend un pointeur de fonction, pas un lambda.
En C++, il y a en général 3 types "d'objets appelables".
Si vous voulez pouvoir utiliser tout cela dans votre interface de fonction, vous pouvez utiliser std::function
:
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, std::function<T(T, U)> f)
{
...
}
Cela permettra à la fonction d'être appelée à l'aide de l'un des trois types d'objets appelables ci-dessus. Cependant, le prix pour cette commodité est une petite quantité de temps système sur les invocations sur la fonction (généralement une vérification de pointeur nulle, puis un appel via un pointeur de fonction). Cela signifie que la fonction n'est presque certainement pas en ligne (sauf peut-être avec advanced WPO / LTO ).
Vous pouvez également ajouter un paramètre de modèle supplémentaire pour prendre un type arbitraire pour le second paramètre. Ce sera plus efficace, mais vous perdrez la sécurité de type sur la fonction utilisée et cela pourrait conduire à une augmentation du code.
template<typename T, typename U, typename F>
map<T,U> mapMapValues(map<T,U> old, F f)
Votre déclaration de type de paramètre T (f)(T,U)
est de type 'fonction libre prenant une T
et une U
et retournant une T
'. Vous ne pouvez pas lui transmettre un lambda, un objet de fonction ou quoi que ce soit, à l'exception d'une fonction réelle portant cette signature.
Vous pouvez résoudre ce problème en changeant le type du paramètre en std::function<T(T,U)>
comme ceci:
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, std::function<T(T,U)>)
{
}
Alternativement, vous pouvez déclarer le type de fonction en tant qu'argument de modèle comme ceci:
template<typename T, typename U, typename Fn>
map<T,U> mapMapValues(map<T,U> old, Fn fn)
{
fn(...);
}
J'aimerais contribuer à cet exemple simple mais qui se passe d'explication. Il montre comment passer des "choses appelables" (fonctions, objets de fonction et lambdas) à une fonction ou à un objet.
// g++ -std=c++11 thisFile.cpp
#include <iostream>
#include <thread>
using namespace std;
// -----------------------------------------------------------------
class Box {
public:
function<void(string)> theFunction;
bool funValid;
Box () : funValid (false) { }
void setFun (function<void(string)> f) {
theFunction = f;
funValid = true;
}
void callIt () {
if ( ! funValid ) return;
theFunction (" hello from Box ");
}
}; // class
// -----------------------------------------------------------------
class FunClass {
public:
string msg;
FunClass (string m) : msg (m) { }
void operator() (string s) {
cout << msg << s << endl;
}
};
// -----------------------------------------------------------------
void f (string s) {
cout << s << endl;
} // ()
// -----------------------------------------------------------------
void call_it ( void (*pf) (string) ) {
pf( "call_it: hello");
} // ()
// -----------------------------------------------------------------
void call_it1 ( function<void(string)> pf ) {
pf( "call_it1: hello");
} // ()
// -----------------------------------------------------------------
int main() {
int a = 1234;
FunClass fc ( " christmas ");
f("hello");
call_it ( f );
call_it1 ( f );
// conversion ERROR: call_it ( [&] (string s) -> void { cout << s << a << endl; } );
call_it1 ( [&] (string s) -> void { cout << s << a << endl; } );
Box ca;
ca.callIt ();
ca.setFun (f);
ca.callIt ();
ca.setFun ( [&] (string s) -> void { cout << s << a << endl; } );
ca.callIt ();
ca.setFun (fc);
ca.callIt ();
} // ()
Voici quelques exemples montrant comment passer une fonction en paramètre
class YourClass
{
void YourClass::callback(void(*fptr)(int p1, int p2))
{
if(fptr != NULL)
fptr(p1, p2);
}
};
void dummyfunction(int p1, int p2)
{
cout << "inside dummyfunction " << endl;
}
YourClass yc;
// using a dummyfunction as callback
yc.callback(&dummyfunction);
// using a lambda as callback
yc.callback( [&](int p1, int p2) { cout << "inside lambda callback function" << endl; } );
// using a static member function
yc.callback( &aClass::memberfunction );