2017-12-02 162 views
9

Podczas odpowiadania na How do I write a lambda expression that looks like a method?, próbowałem przekształcić bezobsługową lambdę w wskaźnik funkcji elementu, wykorzystując fakt, że od C++ 17, przechwytujące lambdy mają operatora konwersji constexpr do ich typu wskaźnika funkcji.Czy mogę użyć wyniku przechwytywania operatora C++ 17 bez operatora lambda constexpr jako argumentu wskaźnika szablonu typu non-type?

Więc wymyśliłem problem wrzenia w dół do:

template<void(*)()> struct A{}; 

int main() 
{ 
    A<static_cast<void(*)()>([]{})>{}; // 1 

    constexpr auto fp = static_cast<void(*)()>([]{}); 
    A<fp>{}; // 2 
} 

Teraz, to kompiluje w brzękiem (od 5.0.0) ale gcc (> = 7.2) narzeka:

error: lambda-expression in template-argument 
    A<static_cast<void(*)()>([]{ /*whatever*/ })>{}; // 1 
          ^
error: 'main()::<lambda()>::_FUN' is not a valid template argument for type 'void (*)()' because 'static constexpr void main()::<lambda()>::_FUN()' has no linkage 
    A<fp>{}; // 2 

Pytanie brzmi: kto ma rację?

+1

Powinien istnieć prostszy przykład użycia zmiennych lokalnych constexpr, nie? – Yakk

+0

@Tak, gotowe; to jednak nie jest w pełni równoznaczne z oryginalnym kodem ... czy nie? –

+0

Nie mogę przestać się zastanawiać, co dokładnie robisz i dlaczego jest to potrzebne. –

Odpowiedz

3

To jest błąd w gcc, złożony 83258.

W C++ 14 używaliśmy linkage requirement dla nie szablonowych parametrów typu wskaźnika. Ale w C++ 17 (w wyniku N4268), parametr musi być po prostu converted constant expression właściwego typu, z kilkoma innymi ograniczeniami (z których żaden nie jest tutaj odpowiedni). Kiedy będziemy mogli zbudować fp, powinniśmy być w stanie użyć go jako parametru szablonu.