Comment surcharger une simple fonction lambda locale?
SSE du problème d'origine:
#include <iostream>
#include <map>
void read()
{
static std::string line;
std::getline(std::cin, line);
auto translate = [](int idx)
{
constexpr static int table[8]{ 7,6,5,4,3,2,1,0 };
return table[idx];
};
auto translate = [](char c)
{
std::map<char, int> table{ {'a', 0}, {'b', 1}, {'c', 2}, {'d', 3},
{'e', 4}, {'f', 5}, {'g', 6}, {'h', 7} };
return table[c];
};
int r = translate(static_cast<int>(line[0]));
int c = translate(static_cast<char>(line[1]));
std::cout << r << c << std::endl;
}
int main()
{
read();
return 0;
}
Les messages d'erreur
error: conflicting declaration 'auto translate'
note: previous declaration as 'read()::<lambda(int)> translate'
S'il vous plaît, ne vous occupez pas de ne pas vérifier les entrées utilisateur, il s'agit d'un SSE.
translate
ne sont que des variables locales qui ne peuvent pas réutiliser le même nom.Réponses:
Non, vous ne pouvez pas surcharger le lambda!
Les lambdas sont des foncteurs anonymes (c'est-à-dire des objets de fonction sans nom) et non des fonctions simples. Par conséquent, la surcharge de ces objets n'est pas possible. Ce que vous essayez essentiellement de faire est presque
Ce qui n'est pas possible, car le même nom de variable ne peut pas être réutilisé en C ++.
Cependant, en c ++ 17, nous avons
if constexpr
par lequel on peut instancier la seule branche qui est vraie au moment de la compilation.Cela signifie que les solutions possibles sont:
decltype
de laif constexpr
vérification. (Crédits @NathanOliver )En utilisant un modèle variabe, vous pouvez faire quelque chose comme. ( Voir une démo en direct en ligne )
et l'appelle comme
En utilisant lambda générique (depuis c ++ 14 ), ce qui précède sera: ( Voir une démo en direct en ligne )
et appelez le lambda comme vous le faites maintenant:
la source
else if
besoins doivent l'êtreelse if constexpr
. Deuxièmement, pourquoi utiliser un modèle de variable? Vous pourriez simplement faire le lambda générique et vos checls deviendraientif constexpr (std::is_same_v<decltype(idx), int>)
etelse if constexpr (std::is_same_v<decltype(idx), char>)
Les lambdas sont essentiellement du sucre syntaxique pour les foncteurs définis localement. Pour autant que je sache, ils n'ont jamais été destinés à être surchargés pour être appelés avec des paramètres différents. Notez que chaque expression lambda est d'un type différent, donc même l'erreur immédiate mise à part, votre code ne peut pas fonctionner comme prévu.
Vous pouvez cependant définir un foncteur avec un surchargé
operator()
. Ce sera exactement ce que vous obtiendriez de lambdas si c'était possible. Vous n'avez tout simplement pas la syntaxe laconique.Quelque chose comme:
la source
Les règles de surcharge des noms ne s'appliquent donc qu'à certains types de recherche de noms de fonctions (libres et méthodes).
Les lambdas ne sont pas des fonctions, ce sont des objets avec un opérateur d'appel de fonction. Une surcharge ne peut donc pas se produire entre deux lambdas différents.
Maintenant, vous pouvez obtenir une résolution de surcharge pour travailler avec des objets fonction, mais uniquement dans le cadre d'un seul objet. Et puis s'il y en a plusieurs
operator()
, la résolution de surcharge peut choisir entre eux.Un lambda, cependant, n'a aucun moyen évident d'en avoir plus d'un
operator()
. Nous pouvons écrire une classe utilitaire simple (en c ++ 17 ) pour nous aider:et un guide de déduction:
avec ces deux, nous pouvons surcharger deux lambdas:
Et.. Voila.
L'écriture
overloaded
est possible à la fois en c ++ 14 et c ++ 11 mais nécessite plus de travail et est moins élégante. Une fois que vous êtes conscient du problème, trouver une solution qui correspond à ce que votre compilateur prend en charge en termes de fonctionnalités C ++ ne devrait pas être difficile.la source
variadic generic lamda
+if constexpr
pour séparer les appels?