2010-12-11 18 views
8

He redefinido algunas funciones matemáticas (para que sean más rápidas, es decir, menos precisas, o use plantillas). Puse estas funciones en un espacio de nombres y funcionan muy bien.C++: ocultar algunas funciones

Sucede a menudo, sin embargo, que me olvide de llamar a las funciones de mi espacio de nombres (es decir: me olvide de escribir mymath::cos o using mymath::cos; cuando quiero llamar cos), y es bastante difícil de averiguar dónde se me olvidó (hasta ahora lo descubrí solo mediante perfiles).

Dado que

  • sóloincluyen estándar math.h o cmath encabezados dentro de mi cabecera matemáticas, y que
  • necesito incluir cabeceras de matemáticas estándar (porque algunos de mis funciones son sólo envoltorios para el estándar uno, y yo quiero que sean en línea o que están en plantilla),

hay una manera portátil para ocultar función matemática estándar para que se informe de un error de compilación, si se utilizan las funciones matemáticas del espacio de nombres global (es decir: sin un espacio de nombres)?

Una solución podría estar poniendo un using namespace mymath; en la parte inferior de mi archivo de encabezado matemático, pero esta solución no parece tan buena: rompe el propósito de los espacios de nombres; Prefiero tener que explicar explícitamente si debo usar una función de mymath o de std, de modo que me veo obligado a elegir entre una función más fina o más precisa sin el riesgo de olvidarme de ella.


EDITAR:

Muchas de las respuestas dicen que si uso cos del espacio de nombres global (sin utilizar ni stdmymath), e incluyen cmath (y no math.h), compilación fallara.

No sé lo que la norma dice al respecto, pero:

#include <cmath> 
int main() { 
    cos(M_PI); 
    return 0; 
} 

compila bien con GNU GCC (g++) 4.5.1 (y versiones anteriores).

+0

Tiene razón con respecto al EDIT: "No se especifica si estos nombres se declaran por primera vez dentro del ámbito del espacio de nombres global y luego se inyectan en el espacio de nombres std mediante declaraciones de uso explícitas". – ybungalobill

Respuesta

4

poner esto en un archivo de cabecera, y #include en todas partes:

namespace DontUseMe { 
double cos (double) ; 
// ...etc. 
} 
using namespace DontUseMe ; 
+0

Uh, esto se ve bien! Usar Boost.StaticAssert me dará errores de tiempo de compilación cada vez que use una función matemática de espacio de nombres global ... – peoro

+3

Bueno, alguien lo votó en contra. ¡Me pregunto porque! – TonyK

+0

Cuando haces esto y en alguna compilación se incluye 'cmath', el compilador te dirá que' double cos (double) 'es ambiguo. De ahí el namespace * wrestling *;) –

3

Si solo incluye cmath y no math.h, todas las funciones de ese encabezado deben estar en el espacio de nombres std ::. Simplemente nunca use using namespace std; y todo irá bien. (cmath es sólo math.h con todas las cosas en un espacio de nombres)

+3

No, no con 'cmath' de GNU GCC 4.5.1.Quiero decir, sí, proporciona funciones matemáticas en el espacio de nombres 'std', pero ** también ** proporciona funciones matemáticas en el espacio de nombres global (es decir:' :: cos', sin ningún espacio de nombres), que es lo que quiero evitar. – peoro

1

¿Qué tal esta idea: después de incluir < math.h>, utilizar definen de la siguiente manera:

#define sin blahblahblah (just to generate an error) 
#define cos blahblahblah (just to generate an error) 

Lo que pasa es que todo pecado será reemplazado por blahblahblah, que causará un error. Pero lo que sucederá es que mymath :: sin será reemplazado por mymath :: blahblahblah (porque #define funciona literalmente), por lo que también generará un error. En este caso, si desea facilitarle la tarea, solo defina temporalmente la función blahblahblah en mymath para evitar que se muestre el error de mymath :: sin, luego compile y corrija todos esos errores.

Sin embargo, recomendaría simplemente hacer "Buscar en archivos" y revisar todas las funciones, y estoy seguro de que no le hablará más de una hora para un proyecto a gran escala.

Espero que ayude.

Saludos,
RAFID

+0

Esta es una posible solución. Las funciones matemáticas estándar de la biblioteca estándar a menudo son macros. –

+0

Hum, esperaba encontrar una manera de hacerlo en tiempo de compilación, sin tener dos pasos para compilar (uno para comprobar la validez de las funciones y el otro para compilar realmente) ... De todos modos sí, esto funcionaría. – peoro

+1

Esto no funcionará, debería definirlos como macros de estilo de función y debería verificarlos y 'undef', ya que se les permite que sean macros (así como también funciones) en' math.h'. Si usa macros de estilo que no son de función, cualquier intento de usar '(std :: sin) (x)' o '(mymath :: sin) (y)' aún sería destruido por estas macros. –

2

¿Necesita incluir las cabeceras math.h y cmath directamente en su archivo de cabecera? Si usted tiene que, trate de incluir la cabecera de esta manera:

namespace arbitrary_name 
{ 
    #include <math.h> 
} 

Este contendrá todas las definiciones math.h dentro de un nuevo espacio de nombres, para que no se use accidentalmente en otro lugar.

Esta no es la solución ideal. Tal vez haya una mejor manera de hacerlo utilizando espacios de nombres anónimos, pero la solución no está clara para mí.

+0

Esto funcionará, pero solo si 'math.h' contiene solo código C. Prefiero incluir 'cmath', por lo que declara muchas funciones sobrecargadas con el mismo nombre de funciones estándar (es decir:' double cos (double x); ',' float cos (float x); '...) . - De todos modos, creo que esto es lo mejor que puedo hacer ... – peoro

+0

The River, esto no funcionará ya que todos los símbolos exportados por esa lib no están en el espacio de nombres en el que pones el encabezado. –

2

Lamentablemente, la solución más sólida será no utilizar los mismos nombres de funciones que la biblioteca estándar. Afortunadamente, los nombres de funciones estándar son escuetos y muy abreviados, por lo que nombres como cosine(), sine(), exponent(), arctan() serían únicos (y posiblemente mejores) sin tener que adornar el nombre con los torpes prefijos.

Alternativamente, usted puede mantener los mismos nombres, pero capitalizarlos: Sin(), Cos(), etc. Exp()

+0

Por supuesto, funcionará , pero como olvido usar explícitamente un espacio de nombres dado, estoy seguro de que a menudo me olvidaré de usar mis nombres personalizados para las funciones estándar. Sin embargo, sería más fácil encontrar donde uso nombres de funciones estándar ... – peoro

+0

Prefiero buscar el nombre completo que jugar con mayúsculas. –

+0

@Matthieu: Estoy totalmente de acuerdo, es horrible, pero puede atraer a algunos. – Clifford

1

Escribir algunas funciones de contenedor en un archivo separado.

#include <math.h> 

namespace my_wrapper 
{ 

float sin(float n) 
{ 
    return std::sin(float n); 
} 

}; 

O algo así. Y luego solo use esos en sus otros archivos y ni siquiera los incluya o en los otros archivos soure. Sí, es un poco doloroso escribir funciones de reenvío para todos, pero es solo un trabajo aislado y no hay tantos ...

Con un compilador moderno que enlaza la generación de códigos de tiempo y puede alinear en archivos de objeto este no debe ser ineficiente ...

+0

¿Qué tal las plantillas? 'template PROMOTE (T1, T2) pow (T1 x, T2 y) {return std :: pow ((PROMOCIONA (T1, T2)) x, (PROMOCIONA (T1, T2)) y) ; } '? ('PROMOTE' es una macro que definí que usa plantillas para promocionar tipos, es decir: PROMOTE (int, double) es doble). – peoro

+0

@ peoro: use 'export'. – ybungalobill

+0

'export' no es C++ 0x estándar. – peoro

0

de Clifford mi respuesta favorita hasta ahora, pero no hay otra alternativa es posible prever: modificar el encabezados estándar para este proyecto (solo).

Debería haber una opción con su compilador de elección para indicar dónde se encuentra la biblioteca estándar, por lo tanto puede duplicar el STL en su proyecto y modificar los archivos para que los nombres ofensivos ya no se inyecten en el espacio de nombres global.

Es hacker, pero esa es la única manera que se me ocurre, a falta de comprobar el código con una secuencia de comandos para cualquier ocurrencia de cos/sin que no está calificado (es decir, precedido inmediatamente por ::).