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