Sont typedefs fonction locale visible dans C ++ 0x lambdas?
-
22-09-2019 - |
Question
J'ai rencontré un problème étrange. Le code simplifié suivant reproduit le problème dans MSVC 2010:
template <typename T>
struct dummy
{
static T foo(void) { return T(); }
};
int main(void)
{
typedef dummy<bool> dummy_type;
auto x = []{ bool b = dummy_type::foo(); };
// auto x = []{ bool b = dummy<bool>::foo(); }; // works
}
Le typedef
j'ai créé localement dans la fonction ne semble pas être visible dans le lambda. Si je remplace le typedef
avec le type réel, il fonctionne comme prévu.
Voici quelques autres cas de test:
// crashes the compiler, credit to Tarydon
int main(void)
{
struct dummy {};
auto x = []{ dummy d; };
}
// works as expected
int main(void)
{
typedef int integer;
auto x = []{ integer i = 0; };
}
Je n'ai pas g ++ disponible pour le tester, en ce moment. Est-ce une règle étrange dans C ++ 0x, ou tout simplement un bogue dans le compilateur?
A partir des résultats ci-dessus, je me penche vers bug. Bien que l'accident est sans aucun doute un bug.
Pour l'instant, je l'ai déposé deux rapports de bogue .
Tous les extraits de code doivent compiler ci-dessus. L'erreur doit faire avec l'aide de la résolution de portée sur les étendues définies localement. (Repéré par dvide .)
Et le bug de plantage doit faire avec ... qui sait. :)
Mise à jour
Selon les rapports de bogue , ils ont tous deux été fixés pour la prochaine version de Visual studio 2010. (Bien que cela ne semble pas être le cas,. VS11 peut-être)
La solution
De N3000, 5.1.2 / 6,
Le lambda de l'expression instruction_compound donne le fonction-corps (8,4) de la fonction appel opérateur, mais à des fins de recherche de nom (3.4), ... la -Instruction composée est considérée dans le contexte du lambda-expression.
Sans surprise, le type local doit être visible.
Autres conseils
ne peuvent pas être détectés énumérations de fonction locale par lambdas soit.
int main()
{
enum E {A, B, C};
auto x = [](){ int a = A; };
//auto y = [](){ E a = A; }; // this will crash the compiler
}
erreur C3493: « A » ne peut pas être capturé implicitement parce qu'aucun mode de capture par défaut a été spécifié
Voici une workround, problématique, peut-être bien.
int main()
{
enum E {A, B, C};
auto x = [=](){ int a = A; };
// typedef E F;
// auto y = [=](){ F a = A; }; // this compiles ok
}
Ce n'est pas vraiment une réponse à votre question, mais simplement d'explorer le problème. Je me demandais si le compilateur a des problèmes traitant de types a déclaré dans une portée englobante, donc essayé ceci:
#include <iostream>
template <typename Func>
void do_test(Func pFunc) {
}
template <typename T>
void test_trait(void) {
class Something { public: int foo; };
do_test ([] (T pX) {
Something A; A.foo = 12;
});
}
int main(void) {
test_trait<int> ();
}
Ici, je vais juste essayer de créer un type local dans le périmètre qui entoure et l'utiliser dans la fonction lambda. Non seulement cela ne compile pas (avec Visual Studio 2010, Beta 2), mais il se bloque en fait le compilateur avec une erreur interne C1001.
Je l'ai déposé deux rapports de bogues.
Nous verrons comment ça se passe. :)
Mise à jour
Les deux bugs ont été marqués comme fixes:
Nous apprécions vos commentaires. Ce bug a été vu par nous avant et nous l'avons fixé à la prochaine version. Merci d'utiliser le produit.
Merci,
Ulzii Luvsanbat
Windows équipe C ++
Alors là, nous allons.