2015-07-02 12 views
18

Przede wszystkim wiem, że mogłem użyć szablonowej klasy/funktora, ale to nie jest to, czego chcę.Czy ogólna lambda nie ma argumentów?

Oto lambda:

auto lambda = [] (auto var) { 
    decltype(var) x; 

    //do stuff with x but nothing with var 
}; 

Problemem jest to, że otrzyma ostrzeżenie C4100 (przypisań parametr formalny). Wiem też, że mógłbym używać sztuczek, takich jak wyłączanie ostrzeżenia i włączanie go ponownie po lambda lub przy użyciu makr, takich jak UNREFERENCED_PARAMETER, ale to jest oszukiwanie.

Czy mogę to osiągnąć?

Idealnym kod będzie wyglądać następująco:

template <typename T> 
auto lambda = []() { 
    T x; 

    //do stuff with x 
}; 
+1

Jakiej wersji kompilatora używasz? – tadman

+1

Używam MSVC 2015 RC. – Nighteen

+0

Jestem ciekawy, dlaczego nie chcesz używać var, ponieważ został przekazany do ciebie według wartości, więc jest to już twoja lokalna kopia zmiennej. Natychmiastowe ogłaszanie drugiego takiego wydaje się zbędne. Konkretnie, 'var' to' auto', więc stracił wszelkie właściwości odniesienia itp., Podczas gdy 'x' to' decltype (var) '. – kfsone

Odpowiedz

17

W rzeczywistości, w C++ 14 można utworzyć „Szablon lambdy” używając dokładnie składni chcesz, ale tylko w zakresie przestrzeni nazw:

// (1) 
template <typename T> 
auto l = []() { 
    T x; 
}; 

int main() { 
    l<int>(); 
} 

to nie jest nazwą rodzajową lambda, to zmienna szablonu ale można nawet stworzyć ogólny szablon lambda:

template <typename T> 
auto l = [] (auto y) { 
    T x = 42; 
    std::cout << x + y << std::endl; 
}; 

Demo

ale jest minusem: wydaje się, że wśród obecnych kompilatory tylko Clang obsługuje t jego.

Aktualizacja: Ponieważ można to zrobić tylko w zakresie przestrzeni nazw, jeśli lambda ma żadnych argumentów, lub nie posiada auto argumenty (to znaczy, że nie jest to ogólne), może być zastąpione przez funkcję bez konieczności nawet wszelkie funkcje C++ 11, nie wspominając o C++ 14. Jeśli taka lambda przechwytuje, może przechwytywać tylko zmienne globalne, więc odpowiednia funkcja może po prostu używać tych samych zmiennych lub ich kopii. Dzięki @JasonR za wskazanie tego:

// effectively the same as (1) 
template <typename T> 
void l() { 
    T x; 
} 
+1

Dzięki za odpowiedź, właśnie tego szukałem. – Nighteen

+1

@ user2565020 Nie sądzę, że to ci pomoże, ponieważ VS2015 [nie obsługuje szablonów zmiennych] (http://blogs.msdn.com/b/vcblog/archive/2015/06/19/c-11- 14-17-features-in-vs-2015-rtm.aspx). Dodałem tę odpowiedź tylko dla kompletności. –

+2

Zgadzam się, ale mój kod może trwać od 2 do 3 lat. – Nighteen

8

Jeśli naprawdę nie potrzebują argumentów, po prostu zawinąć go w void:

auto lambda = [](auto var) { 
    (void)var; // now we used it - more or less 
    decltype(var) x; 
    /* whatever else */ 
}; 
+4

Nie jest to piękne, nowoczesne rozwiązanie, ale to dlatego, że nie istnieje (oprócz użycia odpowiednich narzędzi do pracy) +1 –

+0

Tak, właśnie to robi UNREFERENCED_PARAMETER, ale dzięki za poświęcenie czasu odpowiedź: – Nighteen

+0

@Barry: Haha Zapomniałem –

6

To nie jest to, co lambdas są za, i nie ma na to żadnej składni (oprócz ostrzeżenia).

Wystarczy napisać odpowiedni szablon funkcji. Nie wszystko musi być lambda.

3

Nie, ogólny lambda nie może mieć żadnych argumentów, ponieważ nie ma argumentów do wyprowadzenia typu z. Będziesz musiał użyć funktora zastępczego z szablonem.

6

Nie używaj lambda:

template<typename T> 
struct Functor 
{ 
    void operator()() { T var; ... } 
} 

lambda nie jest niczym innym, kompilator generowane funktor.

+0

Dokładnie to, co powiedziałem, nie powinno być zrobione. :) – Nighteen

+3

@ user2565020: Nieważne. –

Powiązane problemy