tipos sacar programacion numero funcion ejemplos constantes como comando calcular agregar c++ namespaces cmath

c++ - sacar - math.h pi



¿Por qué algunas funciones en<cmath> no están en el espacio de nombres estándar? (3)

Estoy desarrollando un proyecto que trabaja con múltiples tipos aritméticos. Así que hice un encabezado, donde se definen los requisitos mínimos para un tipo aritmético definido por el usuario:

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); ... }

Lo que me preocupa es que cuando uso un código como este:

#include "user_defined_arithmetic.h" void some_function() { using namespace arithmetic; ArithmeticF lala(3); sin(lala); }

Me sale un error de compilación:

error: call of overloaded ''sin(ArithmeticF&)'' is ambiguous candidates are: double sin(double) const ArithmeticF arithmetic::sin(const ArithmeticF&)

Nunca he usado el <math.h> , solo el <cmath> . Nunca he usado el using namespace std en un archivo de encabezado.

Estoy usando gcc 4.6. *. Verifiqué cuál es el encabezado que contiene la declaración ambigua y resulta ser:

mathcalls.h:

Prototype declarations for math functions; helper file for <math.h>. ...

Sé que <cmath> incluye <math.h> , pero debería proteger las declaraciones por el espacio de nombres estándar. <cmath> encabezado <cmath> y encuentro:

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) { ...

Entonces el espacio de nombres std comienza después de #include <math.h> . ¿Hay algo mal aquí, o malentendí algo?


Esto es solo un humilde intento de comenzar a resolver este problema. (Las sugerencias son bienvenidas.)

He estado lidiando con este problema desde hace mucho tiempo. Un caso donde el problema es muy obvio es este caso:

#include<cmath> #include<iostream> namespace mylib{ std::string exp(double x){return "mylib::exp";} } int main(){ std::cout << std::exp(1.) << std::endl; // works std::cout << mylib::exp(1.) << std::endl; // works using namespace mylib; std::cout << exp(1.) << std::endl; //doesn''t works!, "ambiguous" call return 0; }

Esto es, en mi opinión, un error molesto o al menos una situación muy desafortunada. (Al menos en GCC, y clang --utilizando la biblioteca de GCC-- en Linux.)

Últimamente le di otra oportunidad al problema. Al observar el cmath (de GCC) parece que el encabezado está allí simplemente para sobrecargar las funciones C y estropea el espacio de nombres en el proceso.

namespace std{ #include<math.h> } //instead of #include<cmath>

Con esto esto funciona.

using namespace mylib; std::cout << exp(1.) << std::endl; //now works.

Estoy casi seguro de que esto no es exactamente equivalente a #include<cmath> pero la mayoría de las funciones parecen funcionar.

Lo peor de todo es que eventualmente alguna biblioteca de dependencia eventualmente se #inclulde<cmath> . Por eso no pude encontrar una solución todavía.

NOTA : No hace falta decir que esto no funciona en absoluto.

namespace std{ #include<cmath> // compile errors }


Las implementaciones de la biblioteca estándar de C ++ están autorizadas a declarar las funciones de la biblioteca C en el espacio de nombres global, así como en std . Algunos lo llamarían un error, ya que (como ha encontrado) la contaminación del espacio de nombres puede causar conflictos con sus propios nombres. Sin embargo, así es como es, así que debemos vivir con ello. Tendrás que calificar tu nombre como arithmetic::sin .

En las palabras de la norma (C ++ 11 17.6.1.2/4):

Sin embargo, en la biblioteca estándar de C ++, las declaraciones (excepto los nombres que se definen como macros en C) están dentro del alcance del espacio de nombres (3.3.6) del espacio de nombres std . No se especifica si estos nombres se declaran primero en el ámbito del espacio de nombres global y luego se inyectan en el espacio de nombres estándar mediante declaraciones de uso explícitas (7.3.3).


Si realmente quisieras, siempre podrías escribir un pequeño envoltorio alrededor de cmath , en la línea de:

//stdmath.cpp #include <cmath> namespace stdmath { double sin(double x) { return std::sin(x); } } //stdmath.hpp #ifndef STDMATH_HPP #define STDMATH_HPP namespace stdmath { double sin(double); } #endif //uses_stdmath.cpp #include <iostream> #include "stdmath.hpp" double sin(double x) { return 1.0; } int main() { std::cout << stdmath::sin(1) << std::endl; std::cout << sin(1) << std::endl; }

Supongo que podría haber algo de sobrecarga por la llamada a la función adicional, dependiendo de lo inteligente que sea el compilador.