Impossible d'instancier des modèles de fonction qui utilise decltype pour en déduire le type de retour, si elle est appelée à l'intérieur d'un lambda?

StackOverflow https://stackoverflow.com/questions/2335530

Question

Je suis en train d'utiliser C ++ 0x, et en particulier l'expression lambda et decltype pour simplifier une partie de mon code, en utilisant le compilateur RC MSVC10.

J'ai couru dans le problème suivant très étrange:

template <typename F>
auto foo(F f) -> decltype(f()){
  return f();
}

template <typename F>
void bar(F f){
  f();
}

int main() {
  bar([](){
    foo([]() { }); // error C2893: Failed to specialize function template ''unknown-type' foo(F)'
  });
}

Comme l'indique le commentaire, le compilateur génère une erreur sur la ligne foo([]() { }).

Je déteste crier « bug du compilateur », mais je ne vois vraiment pas une bonne explication pour cette erreur. Apparemment, alors que dans l'expression lambda externe, le compilateur ne peut pas spécialiser le modèle de fonction foo pour le lambda intérieur.

Cependant, si la définition de foo est modifiée pour coder le type de retour, comme ceci:

template <typename F>
void foo(F f){
  return f();
}

puis tout compile très bien.

Y at-il une certaine bizarrerie obscure de decltype lorsqu'il est utilisé pour en déduire le type de retour des paramètres d'expression lambda dans le cadre d'un autre lambda que je ne suis pas au courant?

Était-ce utile?

La solution

Ce ne sont que des cas de test pour les gens à observer.

Travaux

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

void dummy() {}

int main()
{
    auto x = []()
            {   // non-lambda parameter
                foo(dummy);
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto f = [](){};
    auto x = [&]()
            {    // pre-defined lambda
                foo(f);
            };
}

Fails

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-argument lambda
                foo([]{});
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-scope lambda
                auto f = []{};
                foo(f);
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-scope lambda, explicit return
                // (explicit return type fails too, `-> void`)
                auto f = [](){ return; };
                foo(f);
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-argument lambda, explicit return non-void
                // (explicit return type fails too, `-> int`)
                foo([]{ return 5; }); 
            };
}

Il ne semble pas avoir à faire avec la portée et le type de void du lambda interne, même si explicite. (?)

Autres conseils

La nature « auto » est compilateur permet de calculer le type. Mais votre premier exemple est contient des références récurrentes sur l'autre, afin de calculer automatiquement de foo de vous besoin de la barre et de créer une instance de bar, vous avez besoin du foo.

D'autre part deuxième exemple indique explicitement le compilateur: « Il doit être un pointeur à la fonction, si calme vers le bas pendant un certain temps ». Étant donné que le pointeur de fonction est compilateur de type bien calculé sait ce qui sera réservé exactement. Juste pour analogique: comparer déclaration avant de membre

struct A; //forward
...
A a1; //this is an error
A *a2; //this is correct since pointer calculated in bytes
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top