2015-12-31 9 views
9

Nel this article, il seguente codice è presentato:tipo Compiler-dedotto per lambda generici

std::vector<int> ivec = { 1, 2, 3, 4}; 
std::vector<std::string> svec = { "red", "green", "blue" }; 
auto adder = [](auto op1, auto op2){ return op1 + op2; }; 
std::cout << "int result : " 
      << std::accumulate(ivec.begin(), 
          ivec.end(), 
          0, 
          adder) 
      << "\n"; 
std::cout << "string result : " 
      << std::accumulate(svec.begin(), 
          svec.end(), 
          std::string(""), 
          adder) 
      << "\n"; 

Se ho capito bene, il compilatore genererà una classe interna molto simile a questo:

template<class T> 
class _lambda 
{ 
    public: 
    T operator()(T lhs, T rhs) { return lhs + rhs; } 
}; 

Ma quello che non capisco è, in questa sezione del codice, adder sembra avere due tipi allo stesso tempo: _lambda<int> e _lambda<string>. Com'è possibile?

risposta

8

Secondo i 5.1.2/P5 lambda espressioni standard di [expr.prim.lambda]:

Per un lambda generica, il tipo di chiusura è un modello di operatore di call membro pubblica funzione inline (14.5. 2) il cui elenco parametri-modello consiste in un parametro modello di tipo inventato per ciascuna occorrenza di auto nella clausola-dichiarazione-clausola lambda, nell'ordine di aspetto .

Di conseguenza, ciò che è effettivamente generato è:

class _lambda { 
public: 
    template<typename T1, typename T2> 
    auto operator()(T1 lhs, T2 rhs) const { return lhs + rhs; } 
}; 
+0

Allo stesso modo, se gli argomenti sono come 'auto && lhs'. quindi genera 'T && lhs' .. e così via. – Nawaz

8

No. Genera qualcosa del genere:

class _lambda { 
public: 
    template<class T1, class T2> 
    auto operator()(T1 lhs, T2 rhs) const { return lhs + rhs; } 
}; 

La classe non è un modello. Lo operator() è.

+0

ah sì, questo ha un senso! grazie – qdii

+0

Allo stesso modo, se gli argomenti sono come 'auto && lhs'. quindi genera 'T && lhs' .. e così via. – Nawaz

+1

@Nawaz nel suo esempio non sono – bolov

1

È un dato di fatto, il compilatore genera una classe simile a questo:

class _lambda { 
public: 
    template<class T, class U> 
    auto operator()(T lhs, U rhs) const { return lhs + rhs; } 
}; 

I due argomenti non sono necessariamente dello stesso tipo, l'unica condizione è l'esistenza di un operator+() con i tipi di argomenti relativi.

Guarda la demo su coliru.

+0

Sono troppo lento :( – YSC

+0

Allo stesso modo, se gli argomenti sono come 'auto && lhs'. Quindi genera' T && lhs' .. e così via. – Nawaz