2013-09-07 9 views
5

Jak wiemy, nie przechwytujące funktory lambda można przekonwertować na wskaźniki funkcji w czasie wykonywania, ale co z czasem kompilacji? Czy możliwe jest coś podobnego do poniższego kodu? Proszę nie sugerować obejścia problemu, np. Przekazanie funktora lambdy jako parametru funkcji, chciałbym dowiedzieć się więcej o tym, gdzie/jak standard C++ 11 zabrania tego.Konwersja czasu kompilacji funktorów lambda na wskaźniki funkcji

template <void(*fptr)()> 
void f() 
{ 
    // do something 
} 

int main() 
{ 
    auto l([]{}); 

    f<(void(*)())(decltype(l))>(); 

    return 0; 
} 

Obowiązkowe błąd z gcc-4.8:

c.cpp: In function 'int main()': 
c.cpp:11:7: error: parse error in template argument list 
     f<(void(*)())(decltype(l))>(); 
    ^
c.cpp:11:36: error: statement cannot resolve address of overloaded function 
     f<(void(*)())(decltype(l))>(); 
            ^
+4

[expr.prim.lambda]/6 "Typ zamknięcia dla niepojedynczego wyrażenia lambda bez przechwytywania lambda ma publiczną, nie-wirtualną, inną niż jawną funkcję konwersji stałej na wskaźnik do funkcji [... ] "i nie musi być" constexpr ". – dyp

+0

@DyP aaahh, działa operator wykonawczy. Wklej jako odpowiedź. – user1095108

+2

Gdybym wiedział * dlaczego * nie musi być "constexpr", to może;) – dyp

Odpowiedz

2

lambda wyrażenia, nawet z pustym zamknięcia, może nie być wykorzystywane jako wskaźnik do funkcji szablonu argumentu, ponieważ są one uzupełnienia tymczasowe który tylko przypadkiem przekonwertować do niektórych wskaźników do funkcji. Wyrażenie lambda jest tymczasowe zgodnie z 5.1.2 [expr.prim.lambda] paragraf 2:

Ocena wyrażenia lambda skutkuje tymczasową prwartością. [...]

konwersja do wskaźnika do funkcji kasowych opisano w ustępie 6:

Rodzaj zamknięcia dla lambda wyrażenia bez lambda-wychwytywania ma zakaz publicznego non wirtualny -explikalna funkcja konwersji stałej do wskaźnika na funkcję mającą ten sam parametr i typy zwracane, co operator wywołania funkcji typu zamknięcia. Wartość zwrócona przez tę funkcję konwersji jest adresem funkcji, która po wywołaniu ma taki sam skutek jak wywołanie operatora wywołania funkcji typu zamknięcia.

Oznacza to, że konwersja nie daje constexpr, a zatem nie ma nadziei, aby użyć wynikowego wskaźnika do działania jako argument szablonu.

Jeśli chodzi o powody, dla których najlepiej mogę znaleźć to na razie oświadczenie w numerze N3597, które wskazuje na N2895, które wydają się mówić o rzeczywistym problemie, ale nie mogłem znaleźć szczegółowej dyskusji. Wydaje się, że wymazywanie nazw dla funkcji tworzonych przez wyrażenia lambda jest jednym z problemów, które zabraniają używania ich w pewnych kontekstach.