web-dev-qa-db-fra.com

Pourquoi la norme C++ 17 n’a-t-elle pas appliqué de déductions partielles des arguments de modèles de classe?

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::maps/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.

13
Kaznov

En une ligne (C++ 17)

std::set s(std::initializer_list<int>{}, [](int a, int b) {return a > b; });
11
max66

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; });
10
Jarod42

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.

5
rubenvb

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.

0
code707