Comment utiliser une expression lambda comme paramètre de template?

comment utiliser l'expression lambda comme paramètre de template? Par exemple: comme classe de comparaison initialisant un std:: set.

la solution suivante devrait fonctionner, puisque l'expression lambda crée simplement une structure anonyme, qui devrait être appropriée comme paramètre de modèle. Cependant, beaucoup d'erreurs sont générés.

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;

erreur de sortie (j'utilise g++ 4.5.1 compiler et -- std=c++0x compiler flag):

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

c'Est que l' comportement attendu ou un bug dans GCC?

EDIT

comme quelqu'un l'a fait remarquer, j'utilise mal les expressions lambda car elles renvoient un exemple de la structure anonyme à laquelle ils font référence.

cependant, corriger cette erreur ne résout pas le problème. J'obtiens lambda-expression in unevaluated context erreur 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
demandé sur Jon 2010-09-28 11:24:36

4 réponses

le deuxième paramètre destd::set attend un tapez, pas expression, c'est juste que vous l'utilisez à tort.

vous pouvez créer l'ensemble 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
répondu kennytm 2010-09-28 07:44:54

pour les comparateurs utilisés de cette façon, vous êtes encore mieux avec 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 cmp_by_x un type local (i.e. le définir à l'intérieur d'une fonction) quand c'est plus pratique, ce qui est interdit par C++courant.

en outre, la comparaison des friandises(x=1, y=1) et(x=1, y=2) comme équivalent. Si ce n'est pas souhaitée, 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
répondu 2010-09-30 09:49:15

pas sûr 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 pouvez utiliser decltype pour éviter de comprendre le type réel (depuis lambdas apparemment ne peut pas être utilisé dans ce contexte.)

ainsi 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
répondu Ken Simon 2016-10-26 21:25:00

le problème est que le dernier paramètre de template est Tapez pas un objet, donc vous pourriez vouloir faire ce qui suit

    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 faire plus simple 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);

cheers

0
répondu yaron kahanovitch 2014-12-25 14:23:02