web-dev-qa-db-fra.com

Comment utiliser une expression lambda en tant que paramètre de modèle?

Comment utiliser l'expression lambda comme paramètre de modèle? Par exemple. en tant que classe de comparaison initialisant un std :: set.

La solution suivante devrait fonctionner, car l'expression lambda crée simplement une structure anonyme, qui devrait être appropriée en tant que paramètre de modèle. Cependant, de nombreuses erreurs sont générées.

Exemple de code:

struct A {int x; int y;};
std::set <A, [](const A lhs, const A &rhs) ->bool {
    return lhs.x < rhs.x;
    } > SetOfA;

Sortie d'erreur (j'utilise le compilateur g ++ 4.5.1 et --std = c ++ 0x drapeau de compilation):

error: ‘lhs’ cannot appear in a constant-expression
error: ‘.’ cannot appear in a constant-expression
error: ‘rhs’ cannot appear in a constant-expression
error: ‘.’ cannot appear in a constant-expression
At global scope:
error: template argument 2 is invalid

Est-ce le comportement attendu ou un bogue dans GCC?

MODIFIER

Comme quelqu'un l'a fait remarquer, j'utilise les expressions lambda de manière incorrecte car elles renvoient une instance de la structure anonyme à laquelle elles font référence.

Cependant, résoudre cette erreur ne résout pas le problème. J'ai l'erreur lambda-expression in unevaluated context pour le code suivant:

struct A {int x; int y;};
typedef decltype ([](const A lhs, const A &rhs) ->bool {
    return lhs.x < rhs.x;
    }) Comp;
std::set <A, Comp > SetOfA;
32
user283145

Le paramètre de modèle 2nd de std::set attend un type , pas une expression , c'est donc que vous l'utilisez mal.

Vous pouvez créer le jeu comme ceci:

auto comp = [](const A& lhs, const A& rhs) -> bool { return lhs.x < rhs.x; };
auto SetOfA = std::set <A, decltype(comp)> (comp);
33
kennytm

Pour les comparateurs utilisés de cette manière, il vaut mieux utiliser une approche non-0x:

struct A { int x; int y; };

struct cmp_by_x {
  bool operator()(A const &a, A const &b) {
    return a.x < b.x;
  }
};

std::set<A, cmp_by_x> set_of_a;

Cependant, dans 0x, vous pouvez faire de cmp_by_x un type local (c'est-à-dire le définir dans une fonction) lorsque cela est plus pratique, ce qui est interdit par le C++ actuel.

De plus, votre comparaison considère A (x = 1, y = 1) et A (x = 1, y = 2) comme équivalents. Si cela n'est pas souhaité, vous devez inclure les autres valeurs qui contribuent à l'unicité:

struct cmp_by_x {
  bool operator()(A const &a, A const &b) {
    return a.x < b.x || (a.x == b.x && a.y < b.y);
  }
};
4
Roger Pate

Vous ne savez pas si c'est ce que vous demandez, mais la signature d'un lambda qui renvoie RetType et accepte InType sera:

std::function<RetType(InType)>

(Assurez-vous de #include <functional>)

Vous pouvez raccourcir cela en utilisant un typedef, mais je ne suis pas sûr que vous puissiez utiliser decltype pour éviter de déterminer le type réel (puisque lambdas ne peut apparemment pas être utilisé dans ce contexte).

Donc, votre typedef devrait être:

typedef std::function<bool(const A &lhs, const A &rhs)> Comp

ou

using Comp = std::function<bool(const A &lhs, const A &rhs)>;
1
Ken Simon

le problème est le dernier paramètre de modèle est le type n'est pas un objet, vous pouvez donc effectuer les opérations suivantes

    std::set <A, std::fuction<bool(const A &,const A &)>> 
              SetOfA([](const A lhs, const A &rhs) ->bool {
                                                             return lhs.x < rhs.x;
                                                          } > SetOfA;

pour simplifier, vous pouvez effectuer les opérations suivantes:

auto func = SetOfA([](const A lhs, const A &rhs) ->bool { return lhs.x < rhs.x;}
set <A,decltype(func)> SetOfA(func);

à votre santé

0
yaron kahanovitch