Sto sviluppando un progetto che funziona con più tipi di aritmetica. Così ho fatto un colpo di testa, in cui sono definiti i requisiti minimi per un tipo aritmetico definito dall'utente:Perché alcune funzioni di <cmath> non si trovano nello spazio dei nomi std?
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);
...
}
Quello che mi è preoccupante è che quando uso il codice come questo:
#include "user_defined_arithmetic.h"
void some_function()
{
using namespace arithmetic;
ArithmeticF lala(3);
sin(lala);
}
ottengo un errore di compilazione:
error: call of overloaded 'sin(ArithmeticF&)' is ambiguous
candidates are:
double sin(double)
const ArithmeticF arithmetic::sin(const ArithmeticF&)
Non ho mai utilizzato l'intestazione <math.h>
, solo lo <cmath>
. Non ho mai usato lo using namespace std
in un file di intestazione.
Sto utilizzando gcc 4.6. *. Ho controllato che cosa è l'intestazione contenente la dichiarazione ambigua e si scopre di essere:
mathcalls.h:
Prototype declarations for math functions; helper file for <math.h>.
...
lo so, che include <cmath>
<math.h>
, ma dovrebbe proteggere le dichiarazioni del spazio dei nomi std. I dig nell'intestazione <cmath>
e trovo:
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)
{
...
Così il namespace std inizia dopo il #include <math.h>
. C'è qualcosa di sbagliato qui, o ho frainteso qualcosa?
Alcune cose che si potrebbe voler riconsiderare: quando si utilizzano i tipi aritmetici (integrante tipi + doppia + float) di solito è più efficiente (e comune) per passare per valore che per riferimento. Quando si chiama una funzione per cui si desidera una versione specifica, si qualifica la chiamata, piuttosto che aggiungere un 'using namespace X'. In alternativa puoi usare un * usando direttiva * ('using arithmetic :: sin'). Infine, l'intero approccio alla modifica dei tipi modificando un typedef è una pessima idea. –
@ DavidRodriguez-dribeas: Grazie! Per favore, potresti suggerirmi una soluzione alternativa? Sto usando il pass per riferimento, perché il numero può essere un tipo personalizzato. Ciò significa che può ottenere anche pochi kilobyte di grandi dimensioni. Speravo che quando inserirò le funzioni e usassi le funzioni elementari std all'interno della linea, non avremo alcun danno. O lo sarà? Potresti darmi qualche suggerimento, per favore? –
@ DavidRodriguez-dribeas: So che l'approccio C++ sarebbe quello di dichiarare una classe astratta, ma una libreria che utilizzo per i calcoli a matrice utilizza significative ottimizzazioni quando si utilizza un tipo incorporato. Non volevo perdere questo vantaggio –