TL; DR
Zgodnie z normą jest to ważne, aby przejść non-arytmetycznych typów jako argumenty cmath
funkcji ale wada zgłosić 2068
twierdzi oryginalny intencją było to, że cmath
funkcje powinny być ograniczone do arytmetycznych rodzajów i wydaje się możliwe, że użycie niearametrycznych argumentów zostanie ostatecznie źle sformułowane. Tak więc, choć technicznie poprawne użycie niearytmetycznych typów jako argumentów wydaje się wątpliwe w świetle raportu o usterkach 2068
.
Szczegóły
Nagłówek cmath jest pokryta projektu normy części 26.8
[c.math] zapewnia dodatkową float i długi podwójne przeciążenia dla każdej funkcji określonej w math.h które ma następnie argument podwójny, akapit 11
zapewnia dostateczne przeciążenie i mówi:
Ponadto, nie będzie dodatkowych przeciążeń wystarczające do zapewnienia:
- Jeżeli którykolwiek argumentem odpowiadające podwójnym parametrem jest typu long double, wszystkie argumenty odpowiadające podwójnych parametrów efektywnie oddane do long double.
- W przeciwnym razie, jeśli jakikolwiek argument odpowiadający podwójnemu parametrowi ma typ double lub typ całkowity, wówczas wszystkie argumenty odpowiadające podwójnym parametrom są skutecznie rzutowane na podwójne.
- W przeciwnym razie wszystkie argumenty odpowiadające podwójnym parametrom są skutecznie rzutowane na zmienną.
Wydaje ważne w C++ 11
w C++ 11 sekcji 26.8
[c.math] nie zawiera żadnych ograniczeń, wykluczający zakaz arytmetyczne argumenty cmath
funkcji. W każdym przypadku od pytania mamy dostępne przeciążenie, które przyjmuje argumenty w postaci podwójnej i należy je wybrać przez overload resolution.
raport Defect 2086
Ale dla C++ 14 mamy defect report 2086: Overly generic type support for math functions, który twierdzi, że pierwotna intencja sekcji 26.8
[c.math] było ograniczenie cmath
funkcje są ważne wyłącznie dla arytmetyczne rodzaje, które naśladują jak oni pracowali w C:
Mam wrażenie, że ten zestaw zasada jest prawdopodobnie bardziej g eneric jako przeznaczone, moim założeniem jest, że jest napisane, aby naśladować zestaw reguł C99/C1x w 7,25 p2 + 3 w sposób "C++" [...] (należy zauważyć, że ograniczenia C prawidłowy zestaw do typów, które C++ opisuje jako typy arytmetyczne, ale zobaczyć poniżej jednej ważnej różnicy) [...]
i mówi:
Moja obecna propozycja, aby rozwiązać te problemy byłoby ograniczyć poprawnych typów argumentu tych funkcji do typów arytmetycznych.
i przeredagowany sekcja 26.8
ustęp 11
powiedzieć (podkr):
Ponadto, nie będzie dodatkowych przeciążeń wystarczająca do zapewnienia:
- Jeżeli którykolwiek arytmetyczną argumentu odpowiadający podwójnemu parametrowi ma typ długi podwójny, następnie wszystkie arytmetyczne argumentów odpowiadających dwóm parametrom jest skutecznie rzutowanych na długie podwójne.
- Inaczej, jeśli arytmetyczna argumentu odpowiadającej podwójnym parametrem jest typu dwu- lub typ całkowitą, wszystkie arytmetyczne argumenty odpowiadające podwójnych parametrów skutecznie przesyłać podwójne.
- W przeciwnym razie wszystkie arytmetyczne argumenty odpowiadające podwójnych parametrów są skutecznie rzucić do
skutecznie rzucić do mieć typ pływaka.
Więc to jest nieważne w C++ 14?
Cóż, pomimo intencji wygląda technicznie nadal ważne jak twierdzi w niniejszym komentarzu z dyskusji w libc++ bug report: incorrect implementation of isnan and similar functions:
które mogły być intencje, ale nie widzę żadnych sposób przeczytaj w ten sposób sformułowanie standardu . Z przykład w komentarzu # 0:
std::isnan(A());
Brak argumentów typu arytmetycznego, więc żaden z pocisków w 26,8/11 stosuje się. Zestaw przeciążeniowy zawiera "isnan (float)", "isnan (double)" i "isnan (long double)", a "isnan (float)" powinno być wybrane .
Tak, przeredagowanie przez DR 2086
ust nie robi to źle sformułowane, aby zadzwonić do pływak, podwójne i long double przeciążeń dostępne w inny sposób z non-arytmetycznych argumentów.
poprawny technicznie, ale wątpliwe, aby korzystać
Więc chociaż standard C++ 11 i C++ 14 nie ograniczają cmath
funkcje do arytmetyki argumenty DR 2068
twierdzi intencją 26.8
ust 11
było ograniczenie cmath
funkcje brać tylko argumenty arytmetyczne i najwyraźniej zamierzał zamknąć lukę w C++ 14, ale nie zapewnił wystarczająco silnych ograniczeń.
Wydaje się wątpliwe, aby polegać na funkcji, która mogłaby się źle uformować w przyszłej wersji standardu. Ponieważ mamy rozbieżność w implementacji, każdy kod, który polega na przekazywaniu nieparametrycznych argumentów do funkcji cmath
dla tych przypadków, jest nieprzenośny i będzie użyteczny tylko w ograniczonych sytuacjach. Mamy alternatywne rozwiązanie, które jest jawnie rzucić zakaz arytmetycznych rodzajów arytmetyczną typy, które omija cały problem, że nie muszą już martwić się o kod staje źle sformułowane i jest przenośny:
std::isgreater(static_cast<double>(s) ,1.0)
^^^^^^^^^^^^^^^^^^^^^^
jak Potatoswatter zaznacza wykorzystaniem pojedynczego +
jest także opcja:
std::isgreater(+s ,1.0)
Aktualizacja
jako TC wskazuje w C++ 11 można stwierdzić, że 26.8
ustęp 11
kula 3
obowiązuje od argumentu nie jest ani long double, podwójne ani liczbą całkowitą, a zatem powinno argumenty typu S
powinny być oddane do pływaka pierwszy . Uwaga, jak wskazano w raporcie o usterkach gcc
nigdy nie zaimplementowałem tego i o ile wiem, nie zrobiłem też clang
.
Prawdopodobnie C++ 11 sformułowanie wymaga 's' być oddane do' float', ponieważ jego typ jest ani '' długo double' ani double' ani typ całkowitą. –
@ T.C.. Wciąż debatują, że jeden, ale tak to jest dyskusyjne. Uwaga, ani '' libC++ ani '' libstdC++ wdrożyć go w ten sposób. –
'+ s' mogą być uznane za idiomatyczne. – Potatoswatter