2010-12-11 11 views
8

Ich habe einige mathematische Funktionen neu definiert (damit sie schneller sind -ich: weniger genau- oder Vorlagen verwenden). Ich stelle diese Funktionen in einen Namensraum und sie funktionieren gut.C++: Einige Funktionen ausblenden

Es kommt oft vor, aber, dass ich Funktionen von meinem Namensraum zu nennen vergessen (dh: Ich mymath::cos oder using mymath::cos; schreiben vergessen, als ich cos nennen will), und es ist ziemlich hart, um herauszufinden, wo ich es vergessen haben (bis jetzt habe ich es nur durch Profiling herausgefunden.

Da

  • I nur umfassen Standard math.h oder cmath Header in meiner Mathe-Header und dass
  • ich brauche Standard-Mathematik-Header enthalten (weil einige meiner Funktionen sind Wrapper nur für Standard , und ich möchte, dass sie inline sein oder sie sind als Templat),

gibt es eine tragbare Art und Weise zu verstecken Standardmathematikfunktion, so dass ein Kompilierfehler gemeldet wird, wenn globale Namespaces (dh: ohne Namespace) mathematische Funktionen verwendet werden?

Eine Lösung könnte eine using namespace mymath; am Ende meiner Math-Header-Datei setzen, aber diese Lösung scheint nicht so toll: Es bricht den ganzen Zweck von Namespaces; Ich möchte lieber explizit sagen, ob ich eine Funktion von mymath oder von std verwenden soll, so dass ich gezwungen bin, zwischen einer Eiter- oder einer genaueren Funktion zu wählen, ohne das Risiko einzugehen, darüber zu vergessen.


EDIT:

Viele Antworten sagen, dass, wenn ich cos von den globalen Namespace verwenden (ohne std noch mymath zu verwenden) und umfassen cmath (und nicht math.h) sollte Kompilierung fehlschlagen.

Ich weiß nicht, was der Standard sagt darüber, aber:

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

mit GNU GCC kompiliert fein (g++) 4.5.1 (und ältere Versionen).

+0

Sie sind richtig in Bezug auf die EDIT: "Es ist nicht angegeben, ob diese Namen zuerst im globalen Namespace-Bereich deklariert werden und dann durch explizite using-Deklarationen in Namespace std injiziert werden". – ybungalobill

Antwort

4

diese in einer Header-Datei, und es überall # include:

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

Äh, das sieht gut aus! Mit Boost.StaticAssert gibt es mir Kompilierzeit Fehler jedes Mal, wenn ich eine globale Namespace mathematische Funktion verwende ... – peoro

+3

Nun, jemand hat es abgelehnt. Ich wundere mich warum! – TonyK

+0

Wenn Sie dies tun und in einer Kompilierungseinheit 'cmath' enthalten ist, sagt Ihnen der Compiler, dass' double cos (double) 'mehrdeutig ist. Daher der Namensraum * wrestling *;) –

3

Wenn Sie nur cmath und nicht math.h einschließen, sollten alle Funktionen aus diesem Header im Namespace std :: sein. Verwenden Sie niemals using namespace std; und alles wird gut. (cmath ist nur math.h mit allen Dingen in einem Namespace)

+3

Nein, nicht mit 'cmath' von GNU GCC 4.5.1.Ich meine, ja, es bietet mathematische Funktionen im 'std' Namespace, aber es ** stellt auch mathematische Funktionen im globalen Namespace zur Verfügung (zB:' :: cos', ohne Namespace), was ich vermeiden möchte. – peoro

1

Wie von dieser Idee: Nach einschließlich < math.h>, verwenden Sie wie folgt definieren:

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

Was passiert, ist, dass jede Sünde ersetzt werden von blahblahblah, was einen Fehler verursachen wird. Aber was passieren wird ist, dass mymath :: sin durch mymath :: blahblahblah ersetzt wird (weil #define wörtlich funktioniert), also wird es auch einen Fehler erzeugen. In diesem Fall, wenn Sie die Aufgabe einfacher für Sie machen möchten, definieren Sie einfach die Funktion blahblahblah in mymath, um Fehler für mymath :: sin zu vermeiden, dann kompilieren Sie und beheben Sie alle diese Fehler.

Ich würde jedoch empfehlen, nur "Find in Files" zu machen und alle Funktionen durchzugehen, und ich bin mir sicher, dass es nicht mehr als eine Stunde für ein sehr großes Projekt sprechen wird.

Hoffe, dass hilft.

Grüße,
Rafid

+0

Dies ist eine mögliche Lösung. Die Standardmathematikfunktionen aus der Standardbibliothek sind oft Makros. –

+0

Hum, hoffte, einen Weg zu finden, dies zur Kompilierzeit zu tun, ohne zwei Schritte zum Kompilieren (eins, um Funktionsgültigkeit zu prüfen, und das andere, um wirklich zu kompilieren) ... Wie auch immer, ja, das würde funktionieren. – peoro

+1

Dies wird nicht funktionieren, Sie müssten sie als Funktionsmakros definieren und Sie müssten sie "abwählen", da sie in "math.h" Makros (sowie Funktionen) sein dürfen. Wenn Sie Makros verwenden, die keine Funktionsstile sind, würde jeder Versuch, '(std :: sin) (x)' oder '(mymath :: sin) (y)' zu verwenden, immer noch von diesen Makros gestört werden. –

2

Möchten Sie die math.h und cmath Header direkt in Ihrem Header-Datei aufgenommen werden müssen? Wenn Sie tun müssen, versuchen einschließlich Header wie folgt aus:

namespace arbitrary_name 
{ 
    #include <math.h> 
} 

Dies wird alle der math.h Definitionen in einem neuen Namespace enthalten, so dass Sie sie nicht versehentlich an anderer Stelle verwenden.

Dies ist keine ideale Lösung. Vielleicht gibt es einen besseren Weg, dies mit anonymen Namensräumen zu tun, aber die Lösung ist mir nicht klar.

+0

Dies funktioniert, aber nur wenn 'math.h' nur C-Code enthält. Ich würde es vorziehen, 'cmath' einzufügen, so dass es viele überladene Funktionen mit dem gleichen Namen von Standardfunktionen deklariert (zB:' double cos (double x); ',' float cos (float x); '...) . - Wie auch immer ich denke, das ist das Beste, was ich tun kann ... – peoro

+0

Der Fluss, dies wird nicht funktionieren, da alle von dieser Bibliothek exportierten Symbole nicht in dem Namespace sind, in den Sie den Header setzen. –

2

Leider ist die robusteste Lösung, nicht die gleichen Funktionsnamen wie die Standardbibliothek zu verwenden. Glücklicherweise sind die Standardfunktionsnamen kurz und stark abgekürzt, so dass Namen wie cosine(), , arctan() eindeutig (und wohl besser) wären, ohne den Namen mit ungeschickten Präfixen schmücken zu müssen.

Alternativ könnten Sie die gleichen Namen behalten, aber nutzen sie: Sin(), Cos(), Exp() usw.

+0

Es wird natürlich funktionieren , aber da ich vergessen habe, einen bestimmten Namespace explizit zu verwenden, werde ich sicherlich vergessen, meine benutzerdefinierten Namen für Standardfunktionen zu verwenden. Es wäre jedoch einfacher zu finden, wo ich Standardfunktionsnamen verwende ... – peoro

+0

Ich würde lieber den vollen Namen wählen als auf die Großschreibung zu spielen. –

+0

@Matthieu: Ich stimme völlig zu, es ist schrecklich, kann aber einige ansprechen. – Clifford

1

einige Wrapper-Funktionen in einer separaten Datei schreiben.

#include <math.h> 

namespace my_wrapper 
{ 

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

}; 

Oder so etwas. Verwenden Sie dann nur die in Ihren anderen Dateien und fügen Sie diese nicht in die anderen Quelldateien ein. Ja, es ist ein kleiner Schmerz, Forwarding-Funktionen für sie alle zu schreiben, aber es ist nur ein One-off-Job und es gibt nicht so viele ...

Mit einem modernen Compiler, der Zeitcode-Generierung verknüpft und inline über Objektdateien kann dies sollte nicht ineffizient sein ...

+0

Wie wäre es mit Vorlagen? 'Vorlage PROMOTE (T1, T2) pow (T1 x, T2 y) {Rückkehr std :: pow ((PROMOTE (T1, T2)) x, (PROMOTE (T1, T2)) y) ; } '? ('PROMOTE' ist ein Makro, das ich definiert habe, das Vorlagen verwendet, um Typen zu promoten - dh: PROMOTE (int, double) ist doppelt). – peoro

+0

@peoro: Verwenden Sie 'export'. – ybungalobill

+0

'export' ist kein C++ 0x Standard. – peoro

0

bisher Clifford ist mein Liebling Antwort, aber es ist eine weitere Alternative, die Sie ins Auge fassen könnten: ändern der Standard-Header für dieses Projekt (nur).

Es sollte eine Option mit Ihrem Compiler Ihrer Wahl geben, um anzugeben, wo die Standardbibliothek liegt. Daher können Sie die STL in Ihrem Projekt duplizieren und die Dateien so ändern, dass die beanstandeten Namen nicht mehr in den globalen Namespace eingefügt werden.

Es ist hackish, aber das ist der einzige Weg, ich, kurz Überprüfung den Code mit einem Skript für das Auftreten von cos/sin, die nicht qualifiziert ist (dh unmittelbar voran von ::) denken kann.