2015-12-31 15 views
9

W this article poniższy kod prezentuje:Compiler-wywnioskować typ dla lambdas generycznych

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"; 

Jeśli dobrze rozumiem, kompilator wygeneruje klasę wewnętrzną dużo jak ten:

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

Ale nie rozumiem, że w tej części kodu adder wydaje się mieć dwa typy w tym samym czasie: _lambda<int> i _lambda<string>. Jak to jest możliwe?

Odpowiedz

8

według standardowych 5.1.2/P5 lambda wyrażenia [expr.prim.lambda]:

generycznego lambda rodzaju zamknięcie ma publicznego rolki funkcja szablon element uruchamiający połączenia (14.5. 2) którego lista szablonów parametrów składa się z jednego wymyślonego szablonu-parametru dla każdego wystąpienia auto w klauzuli-deklaracji parametru lambda, w kolejności od pojawienia się.

konsekwencji, co jest faktycznie generowany jest:

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

Podobnie, jeśli argumenty są podobne 'auto && lhs'. następnie generuje 'T && lhs' .. i tak dalej. – Nawaz

8

Nie. Generuje coś takiego:

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

Klasa nie jest szablonowa. Numer operator().

+0

ah tak, to ma sens! dzięki – qdii

+0

Podobnie, jeśli argumenty są podobne 'auto && lhs'. następnie generuje 'T && lhs' .. i tak dalej. – Nawaz

+1

@Nawaz w swoim przykładzie nie są one – bolov

1

W rzeczywistości, kompilator wygeneruje klasę wygląda tak:

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

Oba argumenty nie są koniecznie tego samego typu, jedynym warunkiem jest istnienie operator+() z odpowiednimi typami argumentów.

Obejrzyj demo pod numerem coliru.

+0

Jestem zbyt powolny :( – YSC

+0

Podobnie, jeśli argumenty są podobne 'auto && lhs'., To generuje 'T && lhs' .. i tak dalej. – Nawaz