Enquête précédente dans Can I make a table of String + lambdas that have the same signature? m'a montré que je peux en fait avoir une table de chaînes + lambdas dans VS2010.Travailler autour de VS2010 bug dans la table de lambdas?
Les choses allaient bien alors que les lambdas étaient vides. Mais ayant essayé de les changer en type de retour booléen, le compilateur semble se tromper, ou il y a une sorte d'erreur de corruption de mémoire ... quelque chose ne va pas en C++ ...
Le scénario suivant illustre le scénario suivant:
// fun: use a table of lambdas to define what to do in order to update each field
typedef std::function<bool (CDynamicMenuItem *, ITEM *)> LambdaType;
struct UpdateField {
const TCHAR * label;
LambdaType lambda; // this version allows us to use captures in our lambdas, whereas the following doesn't
//void (*lambda)(CDynamicMenuItem *, ITEM *); // this would work in VS11, but the conversion of lambda to function pointer was defined after 2010's release!
};
UpdateField MenuFields[] = {
{ "Identity", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { return pMenuItem->SetText(FString("%s/%.1f", pNearestItem->thissec->name, pNearestItem->number/10.0)), true; } },
{ "X1", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetX1(pNearestItem); return (v != v) ? false : pMenuItem->SetValue(v), true; } },
{ "Y1", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetY1(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
{ "X2", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetX2(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
{ "Y2", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetY2(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
{ "Xd", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetXd(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
{ "Yd", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetYd(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
{ "Angle", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetAngle(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
{ "Length", [] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { double v = GetLength(pNearestItem); if (v != v) return false; pMenuItem->SetValue(v); return true; } },
};
for (UpdateField * it = &MenuFields[0], * end = (MenuFields + countof(MenuFields)); it != end; ++it)
{
CDynamicMenuItem * pMenuItem = pMenu->FindItem(it->label);
if (pMenuItem)
{
if (!m_pNearestItem || !it->lambda(pMenuItem, m_pNearestItem))
pMenuItem->SetText("");
}
}
ci-dessus a fonctionné à merveille lorsque le type de retour du lambda est vide (ie -> bool est omis, et les différents organismes lambda sont modifiés pour ne pas retourner quoi que ce soit, etc.).
Cependant, il est utile pour moi de leur renvoyer un bool qui indique si le lambda était capable de traiter les données pour ce champ et, dans le cas contraire, de demander à l'appelant de gérer ce champ.
Pour être certain, le code compile & s'exécute ... jusqu'à ce qu'il frappe ce code & CRASHES. En regardant "MenuFields []" dans le débogueur, la plupart des adresses MenuField [x] .label sont affichées (parfois l'une d'entre elles est correcte, mais je n'ai pas compris le motif). Je pensais que peut-être le compilateur glitching sur la syntaxe de la lambda intégrée dans la liste d'initialisation statique, mais je ne suis pas sûr de ce que je peux faire à ce sujet?
J'ai essayé cette variation:
{ "Identity", LambdaType([] (CDynamicMenuItem * pMenuItem, ITEM * pNearestItem) ->bool { return pMenuItem->SetText(FString("%s/%.1f", pNearestItem->thissec->name, pNearestItem->number/10.0)), true; }) },
Le compilateur aime ça aussi bien, mais il en résulte dans les mêmes données de table corrompues. De même, mettre des parenthèses autour du lambda entier est correct par le compilateur, et également corrompu au moment de l'exécution.
Alors, quelques questions:
- Voyez-vous quelque chose que je négligé? Pouvez-vous penser à un travail pour que le compilateur génère le code correct (autre que revenir à l'annulation de retour - ce qui est plausible pour mon scénario, et ma prochaine étape probable, sauf une meilleure suggestion)?
- Vous savez comment signaler cela à Microsoft? [Je n'ai pas eu de chance de trouver des êtres humains à l'autre bout pour donner ce genre d'information détaillée afin qu'il ne soit pas nul)
Votre typedef ne devrait-il pas indiquer que le type de retour est différent? –
[email protected] # Désolé, mon code est en flux - ma question a été corrigée pour refléter le code corrigé (le compilateur ne compilera même pas à moins d'être d'accord) – Mordachai
"Pour être certain, le code compile & s'exécute". Si c'est le cas, cela ressemble à un problème de débogueur, pas à un problème de compilateur. Les bogues Visual Studio peuvent être signalés dans [Microsoft Connect] (http://connect.microsoft.com/). –