L’un des endroits où j’espérais pouvoir utiliser la nouvelle déduction d’arguments de gabarit était la construction de std::set
'/ std::map
s/de tout autre conteneur avec des comparateurs personnalisés - mon objectif est de créer une instruction d’une ligne qui créera un ensemble efficace. avec un comparateur lambda. Ce que je peux faire depuis C++ 11, c'est:
std::set<int, std::function<bool(int, int)>> s([](int a, int b) {return a > b;});
Mais comme il utilise std::function
, il est visiblement plus lent.
Une autre option est:
auto mycomp = [](int a, int b) {return a > b; };
std::set<int, decltype(mycomp)> s(mycomp);
Le travail est fait, mais 1) Il nécessite 2 lignes et la création de la variable mycomp
2) Je dois passer le type de mycomp
explicitement.
Comme je l'ai lu dans les pages de référence, aucun des conteneurs standard n'a de guide de déduction pour ce genre de situation. Malheureusement, je crains que cela ne puisse même pas être fait avec le standard de langage actuel (C++ 17), car on peut trouver:
La déduction d'argument de modèle de classe n'est effectuée que si aucune liste d'arguments de modèle n'est présente. Si une liste d'arguments de modèle est spécifiée, la déduction n'a pas lieu.
Quel est le raisonnement derrière cela? Pourquoi n'autorisent-ils pas la déduction d'arguments partiels? J'imagine qu'il y a quelques problèmes que je néglige, mais à mon avis, cela serait plus qu'utile.
En une ligne (C++ 17)
std::set s(std::initializer_list<int>{}, [](int a, int b) {return a > b; });
Comme alternative, vous pouvez toujours créer l'ancien make_xxx
template <typename T, typename COMP>
std::set<T, COMP> make_set(COMP comp)
{
return std::set<T, COMP>{comp};
}
auto s = make_set<int>([](int a, int b) {return a > b; });
Ce que vous devriez faire, c’est écrire un type de foncteur comparateur, vous n’avez donc pas besoin de le remplacer par un proxy lorsque vous utilisez votre poste. Ce sera beaucoup plus de lignes de code (l'atrocité!), Mais c'est mieux à presque tous les égards:
struct MyComparator
{
bool operator()(int a, int b) const { ...; }
};
using MySet = std::set<int, MyComparator>;
Et à partir de là, vous créez simplement votre ensemble trié de manière personnalisée où vous en avez besoin.
En raison de l'ambiguïté qu'il apporte, les paramètres de modèle avec la valeur par défaut sont présents. Aussi, en cas de modèles variadiques.