Impossibile istanziare i modelli di funzione che utilizza decltype dedurre tipo di ritorno, se chiamato dall'interno di un lambda?

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

Domanda

Sto cercando di utilizzare C ++ 0x, ed in particolare espressione lambda e decltype per semplificare alcuni del mio codice, usando il compilatore MSVC10 RC.

ho incontrato il seguente problema molto strano:

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

Come indicato nel commento, il compilatore genera un errore sulla linea foo([]() { }).

Io odio a gridare "compilatore bug", ma davvero non riesco a vedere alcuna buona spiegazione per questo errore. A quanto pare, mentre all'interno l'espressione lambda esterno, il compilatore non può specializzare la funzione di modello per foo lambda interiore.

Tuttavia, se la definizione di foo viene modificato in hardcode il tipo di ritorno, in questo modo:

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

poi tutto compila bene.

C'è qualche oscuro scherzo del decltype quando viene utilizzato per dedurre il tipo di ritorno di parametri di espressione lambda all'interno del campo di applicazione di un altro lambda che io non sono a conoscenza?

È stato utile?

Soluzione

Questi sono solo alcuni casi di test per le persone ad osservare.

Opere

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

Fallisce

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

Quindi non sembra avere a che fare con l'ambito e il tipo void del lambda interna, anche se reso esplicito. (?)

Altri suggerimenti

La natura di 'auto' è permettere compilatore per calcolare il tipo. Ma il vostro primo esempio si contiene riferimenti ricorsivi a vicenda, in modo da calcolare automobilistica di foo è necessario il bar e per creare un'istanza della barra è necessario il foo.

D'altra parte secondo esempio dice esplicitamente compilatore: "Dovrebbe essere un puntatore a funzione, in modo calmare per un certo tempo". Dal momento puntatore a funzione è ben calcolato tipo compilatore sa che cosa esattamente sarà riservato. Solo per analogica: confronta dichiarazione anticipata di membro

struct A; //forward
...
A a1; //this is an error
A *a2; //this is correct since pointer calculated in bytes
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top