Je veux créer un std::set avec une fonction de comparaison personnalisée. Je pourrait la définir comme une classe avec l'opérateur(), mais je voulais profiter de la possibilité de définir un lambda où il est utilisé, j'ai donc décidé de définir la fonction lambda dans la liste d'initialisation du constructeur de la classe qui a le std::set en tant que membre. Mais je ne peux pas obtenir le type de la lambda. Avant de poursuivre, voici un exemple:
class Foo
{
private:
std::set<int, /*???*/> numbers;
public:
Foo () : numbers ([](int x, int y)
{
return x < y;
})
{
}
};
J'ai trouvé deux solutions après une recherche: l'un, à l'aide de std::function. Juste le jeu de la comparaison de la fonction de type std::function<bool (int, int)>
, et de transmettre le lambda exactement comme je l'ai fait. La deuxième solution est d'écrire un make_set fonction, comme std::make_pair.
SOLUTION 1:
class Foo
{
private:
std::set<int, std::function<bool (int, int)> numbers;
public:
Foo () : numbers ([](int x, int y)
{
return x < y;
})
{
}
};
SOLUTION 2:
template <class Key, class Compare>
std::set<Key, Compare> make_set (Compare compare)
{
return std::set<Key, Compare> (compare);
}
La question est, dois-je avoir une bonne raison de préférer une solution plutôt que l'autre? Je préfère la première, car elle rend l'utilisation de caractéristiques de série (make_set n'est pas une fonction standard), mais je me demande: est-ce à l'aide de std::function rendre le code (potentiellement) plus lent? Je veux dire, est-il baisser la chance le compilateur inlines la fonction de comparaison, ou il devrait être assez intelligent pour se comporter exactement de la même comme il l'aurait fait il a une fonction lambda de type et pas de std::function (je sais, dans ce cas, il ne peut pas être un type lambda, mais vous savez, je demande en général) ?
(J'utilise GCC, mais j'aimerais savoir ce qu'populaire compilateurs n'en général)
RÉSUMÉ, APRÈS J'AI EU BEAUCOUP DE RÉPONSES:
Si la vitesse est critique, la meilleure solution est d'utiliser une classe avec l'opérateur() aka foncteur. C'est easiesr pour le compilateur d'optimiser et d'éviter toute indirections.
Pour un entretien facilité et une meilleure solution généraliste, à l'aide de C++11 fonctionnalités, de l'utilisation de std::function. C'est toujours rapide (juste un peu plus lent que le foncteur, mais il peut être négligeable) et vous pouvez utiliser la fonction std::function, lambda, tout objet appelable.
Il y a aussi une option pour utiliser un pointeur de fonction, mais si il n'y a pas de problème de vitesse je pense que std::function est mieux (si vous utilisez le C++11).
Il y a une option pour définir la fonction lambda somewher d'autre, mais alors, vous ne gagnez rien à partir de la fonction de comparaison étant une expression lambda, puisque vous pouvez tout aussi bien en faire une classe avec l'opérateur() et l'emplacement de la définition ne serait pas l'ensemble de la construction, de toute façon.
Il y a plus d'idées, comme l'utilisation de la délégation. Si vous voulez une explication plus complète de toutes les solutions, lire les réponses :)