Zgodnie z tą (zaakceptowaną) propozycją, ponieważ C++ 17; ponieważ noexcept jest częścią typu funkcji, czy powyższy kod wydrukuje true
?
Tak.
Rodzaj f
będzie wnioskować do void(*)() noexcept
ponieważ funkcja konwersji do wskaźnika stosowane do asdf
zachowa własność noexcept
. Wywołanie funkcji o wskaźniku funkcji noexcept
nie może z pewnością rzucić wyjątku, chyba że jedno z jego podwyrażeń ma miejsce.
Dokładne brzmienie, patrz [expr.unary.noexcept]/3 i [expect.spec]/13. Zauważ, że nowe sformułowanie w ostatnim akapicie z projektu C++ 17 pochodzi z P0012R1, który jest powiązany w OP.
Wynik operatora noexcept
jest true
jeśli zestaw potencjalnych wyjątkiem tego wyrażenia ([except.spec]) jest pusta, a false
inaczej.
...
e
Jeżeli jest to wywołanie funkcji ([expr.call]):
- Jeśli jego przyrostek ekspresja to (być może w nawiasach) ID ekspresja ([expr.prim.id]), dostęp do elementu klasy ([expr.ref]) lub operacja wskaźnik-do-członka ([expr.mptr.oper]), którego jest wyrażenie o numerze identyfikacyjnymS jest zbiorem typów w specyfikacji wyjątku jednostki wybranej przez zawarte id-expression (po przeciążeniu, jeśli dotyczy). ...
więc zbiór potencjalnych wyjątkami f()
jest taki sam jak zbiór typów w specyfikacji wyjątkiem f
, który jest pusty, ponieważ f
deklaruje noexcept
.
Przejdźmy do drugiego pytania:
noexcept
określające wydaje ignorowane w C++ 14 lub 11. To będzie działać zgodnie z przeznaczeniem kod w C++ 17?
Twoje pytanie brzmi: czy std::function<void() noexcept>
odmówi posiadania funkcji, która może generować wyjątki?
Powiedziałbym, że jest to niejasne: . W obecnym brzmieniu normy, std::function<void() noexcept>
nie jest faktycznie zdefiniowany, tak jak std::function<double(float) const>
is not defined. Nie było to oczywiście problemu w C++ 14, ponieważ noexcept
nie był uważany za część typu funkcji.
Czy std::function<void() noexcept>
po prostu przerwie C++ 17? To jest dla mnie niepewne. Rzućmy okiem na obecne sformułowanie, aby odgadnąć, co to zachowanie powinno "być".
standard wymaga argumentu konstruktora std::function<R(ArgTypes..)>
być „lwartości-niepokryta” typów argumentów ArgTypes...
i rodzaju powrotu R
, które means:
wywoływalnym typu ([func.def]) F
jest Lvalue-Callable dla typów argumentów ArgTypes
i typu zwrotu R
, jeśli wyrażenie INVOKE(declval<F&>(), declval<ArgTypes>()..., R)
, uważane za nieoceniony operand (Clause [wyrażenie]), jest dobrze sformułowane ([func.require]).
Być może powinien istnieć dodatkowy wymóg, że jeśli typ funkcji to noexcept
, wówczas noexcept(INVOKE(...))
musi również być prawdziwe. Niemniej jednak sformułowanie to nie występuje w obecnym projekcie.
W P0012R1, nie jest komentarz, że:
Jest kwestią otwartą, jak propagować "noexcept" przez std::function
.
Domyślam się, że oznacza to, że nie jest jasne, w jaki sposób można wdrożyć std::function
, jeśli nałożono to dodatkowe wymaganie. Mam nadzieję, że ktoś inny może podać więcej szczegółów.
g ++ zwraca 'true' dla' noexcept (f()) 'bez' -std = C++ 1z' (ale clang zwraca 'false'). – Holt
Dla dodatkowej zabawy zmień 'auto f = asdf;' na 'void (* f)() noexcept = asdf;'. Teraz GCC wypisze 'false' podczas gdy clang drukuje' true'. – hvd
@Holt Dzięki za informację. Używam MSVC (zwraca 'false'). Czym różniłyby się od nich? Czy to błąd g ++ lub C++ 14 lub wcześniejszego standardu nie określił niczego w systemie typu "noexcept"? – Gear