C++11 variadic std::paramètre de la fonction
Une fonction nommée test
prend std::function<> comme paramètre.
template<typename R, typename ...A>
void test(std::function<R(A...)> f)
{
//...
}
Mais, si je ne les suivants:
void foo(int n) { /* ... */ }
//...
test(foo);
Compilateur(gcc 4.6.1) dit no matching function for call to test(void (&)(int))
.
De faire la dernière ligne test(foo)
compile et fonctionne correctement, comment puis-je modifier le test()
fonction? Dans test()
fonction, j'ai besoin de f
avec le type de std::function<>.
Je veux dire, est-il un modèle astuces pour laisser le compilateur de déterminer la signature de la fonction(foo
dans l'exemple) et de le convertir en std::function<void(int)>
automatiquement?
MODIFIER
Je veux faire ce travail pour les lambdas(à la fois affirmé et apatrides) ainsi.
Vous devez vous connecter pour publier un commentaire.
Il semble que vous voulez utiliser la surcharge
Cette simple mise en œuvre acceptera la plupart, si pas toutes les fonctions que vous allez essayer de passer. Fonctions exotiques seront rejetés (comme
void(int...)
). Plus de travail vous donnera plus de genericity.test
un modèle qui accepte n'importe quoi (T
).std::function
de ne pas rejeter incompatible la fonction des objets d'emblée de toute façon, l'objectif de limiter le type de la fonction paramètre de modèle ne semble pas trop utile pour moi ici.(T)
, mais, comment peut-il être fait pourstd::function<R(A...)>
? Il semble que je peux obtenirR
à l'aide destd::result_of<>
, maisA...
?std::function
met en œuvre le Callable interface, c'est à dire qu'il ressemble à une fonction, mais cela ne signifie pas que vous devez exiger appelable objets àstd::function
s.Duck-typing est la meilleure politique dans le modèle de la métaprogrammation. Lors de l'acceptation d'un argument de modèle, être explicite et il suffit de laisser le client de mettre en œuvre l'interface.
Si vous vraiment besoin d'un
std::function
par exemple de ré-cible de la variable ou de quelque chose de fou comme ça, et vous savez l'entrée est raw d'un pointeur de fonction, vous pouvez décomposer les raw d'un pointeur de fonction type et reconsitute dans unstd::function
.Maintenant, l'utilisateur ne peut pas passer un
std::function
parce que cela a été encapsulée à l'intérieur de la fonction. Vous pouvez garder votre code existant comme une autre surcharge et simplement déléguer à qui, mais attention à garder des interfaces simples.Comme pour stateful lambdas, je ne sais pas comment gérer ce cas. Ils ne se décomposent à des pointeurs de fonction et autant que je sache, les types d'argument ne peut pas être interrogée ou déduit. Cette information est nécessaire pour instancier
std::function
, pour le meilleur ou pour le pire.duck typing
a été désapprouvéeIl est généralement déconseillé d'accepter
std::function
par valeur, sauf si vous êtes au binaire de délimitation (par exemple, les dynamiques de la bibliothèque, 'opaque' API) depuis que vous avez tout juste d'assister à ils jouent des ravages avec la surcharge. Lorsqu'une fonction n'est en fait prendre unestd::function
en valeur alors que c'est souvent la charge de l'appelant pour construire l'objet pour éviter la surcharge des problèmes (si la fonction est surchargé à tous).Depuis cependant, vous avez écrit un modèle, c'est probablement le cas que vous ne l'utilisez pas
std::function
(comme un type de paramètre) pour les avantages de l'effacement. Si ce que vous voulez faire est de l'inspection arbitraire foncteurs alors vous avez besoin de quelques traits pour que. E. g. Coup de pouce.FunctionTypes a des traits commeresult_type
etparameter_types
. Un minimum, fonctionnel exemple:Comme note finale, je ne recommande pas l'introspection foncteurs (c'est à dire à les pousser pour leur type de résultat et les types d'argument) dans le cas général, en tant que tout simplement ne fonctionne pas pour polymorphes foncteurs. Envisager plusieurs surchargé
operator()
: alors il n'y a pas de "canonique" résultat, le type ou les types d'argument. Avec C++11, c'est mieux avec impatience' accepter tout type de foncteur, ou de les contraindre à l'aide de techniques comme SFINAE oustatic_assert
selon les besoins, et, plus tard, lorsque les paramètres sont disponibles) pour utiliserstd::result_of
pour inspecter le type de résultat pour un ensemble donné d'arguments. Un cas où les contraignant à l'avant est souhaitable, c'est quand le but est de stocker des foncteurs p.ex. dans un conteneur destd::function<Sig>
.Pour obtenir un avant-goût de ce que je veux dire par le paragraphe précédent, il suffit de tester l'extrait ci-dessus avec polymorphes foncteurs.
C'est un ancien, et je n'arrive pas à trouver beaucoup sur le même sujet, j'ai donc pensé que je pourrais aller de l'avant et de le mettre dans une note.
Compilé sur GCC 4.8.2, les ouvrages suivants:
Cependant, vous ne pouvez pas simplement l'appeler en passant votre pointeurs, les lambdas, etc. Cependant, les 2 exemples suivants à la fois de travailler avec elle:
Aussi:
L'inconvénient de ces devrait se démarquer assez évidemment: vous devez déclarer explicitement le std::function, ce qui peut paraître un peu laid.
Cela dit, si, j'ai fait ça avec un tuple qui obtient élargi à l'appel entrant de la fonction, et il fonctionne, exigeant juste un peu plus d'un qui dit explicitement ce que vous êtes en train de faire l'appel de la fonction de test.
Exemple de code, y compris le tuple chose, si vous voulez jouer avec elle: http://ideone.com/33mqZA
std::function
est un tas d'allocation dynamique de la surcharge et de passe-partout pour aucun avantage. Mieux de faire juste une fonction générique modèle qui peut accepter un lambda, que de tirer dansstd::function
tous sur la place.