Pracuję nad projektem, który działa z wieloma typami arytmetycznymi. Więc zrobiłem nagłówek, gdzie są określone minimalne wymagania dla zdefiniowanego przez użytkownika typu arytmetycznego:Dlaczego niektóre funkcje w <cmath> nie są w przestrzeni nazw standardu?
user_defined_arithmetic.h:
typedef double ArithmeticF; // The user chooses what type he
// wants to use to represent a real number
namespace arithmetic // and defines the functions related to that type
{
const ArithmeticF sin(const ArithmeticF& x);
const ArithmeticF cos(const ArithmeticF& x);
const ArithmeticF tan(const ArithmeticF& x);
...
}
Co niepokoi mnie to, że podczas korzystania z kodu tak:
#include "user_defined_arithmetic.h"
void some_function()
{
using namespace arithmetic;
ArithmeticF lala(3);
sin(lala);
}
otrzymuję błąd kompilatora:
error: call of overloaded 'sin(ArithmeticF&)' is ambiguous
candidates are:
double sin(double)
const ArithmeticF arithmetic::sin(const ArithmeticF&)
Nigdy nie użyłem nagłówka <math.h>
, tylko <cmath>
. Nigdy nie użyłem using namespace std
w pliku nagłówkowym.
Używam gcc 4.6. *. Sprawdziłem co jest nagłówek zawierający niejednoznaczne oświadczenia i okazuje się, że:
mathcalls.h:
Prototype declarations for math functions; helper file for <math.h>.
...
wiem, że <cmath>
obejmuje <math.h>
, ale powinna osłonić oświadczeń std przestrzeń nazw. Wbijam w nagłówku <cmath>
i znaleźć:
cmath.h:
...
#include <math.h>
...
// Get rid of those macros defined in <math.h> in lieu of real functions.
#undef abs
#undef div
#undef acos
...
namespace std _GLIBCXX_VISIBILITY(default)
{
...
Więc std nazw zaczyna po#include <math.h>
. Czy coś tu jest nie tak, czy źle coś zrozumiałem?
niektóre rzeczy warto rozważyć: przy użyciu typów arytmetycznych (integralne typy + double + float) jest zwykle bardziej wydajne (i często), aby przejść przez wartość niż przez odniesienie. Podczas wywoływania funkcji, dla której chcesz konkretnej wersji, zakwalifikuj wywołanie, zamiast dodawać 'using namespace X'. Alternatywnie możesz użyć dyrektywy * używającej * ('using arithmetic :: sin'). Wreszcie całe podejście polegające na zmianie typów poprzez edycję 'typedef' jest naprawdę złym pomysłem. –
@ DavidRodriguez-dribeas: Dziękujemy! Proszę, czy mógłbyś wskazać mi alternatywne rozwiązanie? Używam przejścia przez referencję, ponieważ liczba może być niestandardowym typem. Oznacza to, że może osiągnąć nawet kilka kilobajtów. Miałem nadzieję, że kiedy wprowadzę funkcje i użyję podstawowych funkcji elementarnych wewnątrz linii, nic złego się nie stanie. Lub będzie? Czy mógłbyś podać mi jakieś sugestie? –
@ DavidRodriguez-dribeas: Wiem, że podejście C++ byłoby zadeklarować klasę abstrakcyjną, ale biblioteka, której używam do obliczeń macierzowych, używa znaczących optymalizacji, gdy używasz typu wbudowanego. Po prostu nie chciałem stracić tej przewagi. –