2014-11-19 13 views
5

Wenn ich ein wenig Code wie haben:std :: Qualifikationsmerkmal benötigt, wenn überladene Namespace-Funktion existiert?

using namespace std; 

namespace myNamespace 
{ 
    vector<float> sqrt(vector<float> v) { return v; } 

    void func() 
    { 
     vector<float> myVec = { 1, 2, 3, 4 }; 
     std::cout << sqrt(myVec)[0] << std::endl; 
     float myFloat = 4.0f; 
     std::cout << sqrt(myFloat) << std::endl; // need to use std::sqrt() 
    } 
} 

dann wird es nicht kompilieren, wenn ich die markierte Zeile geändert std::sqrt zu verwenden. Warum? Ich verstehe, dass, wenn ich versuchte, sqrt(float) in neu zu definieren, dann würde ich mich mit std:: qualifizieren müssen, wenn ich die Standardbibliotheksversion verwenden wollte. Der Compiler scheint zu versuchen, myFloat zu konvertieren, anstatt nur eine Funktion in einem anderen (std) Namespace zu verwenden.

Ein Weg, ich, dies zu umgehen gefunden ist sqrt(vector<float>) im std Namensraum zu definieren, aber das ist nicht ganz richtig fühlt und Antworten auf this question vorschlagen in std Überlastung illegal ist. Wahrscheinlich nicht der Weg zu gehen dann ...

Wie kann ich sqrt (oder eine andere Standard-Bibliothek cmath-Funktion, für die Angelegenheit) überlasten, so dass ich nicht immer qualifizieren müssen, welche zu verwenden und den Compiler haben basierend auf den übergebenen Funktionsparametern auswählen?

Danke.

+1

im 'std' Namespace eine eigene Funktion Deklarieren definitiv falsch ist. Sie könnten * es im globalen Namespace deklarieren, da Sie 'std' aus irgendeinem Grund dort deponiert haben. Oder Sie könnten '' std :: sqrt; '' neben Ihrem 'sqrt' in Ihren Namensraum einfügen. Ich würde nur den Namen richtig qualifizieren. –

+1

Sie könnten auch einfach nicht verwenden Sie 'using Namespace Somethingsomething' und immer das Präfix std ::, Vermeidung von Mist wie diese insgesamt. – Cubic

Antwort

9

In C++ wählen, name lookup schert sich nicht um Parameter Typ , nur der Name zählt. Wenn der Compiler nach einer Funktion mit dem Namen sqrt sucht, findet er immer zuerst Ihre Version (da die Suche mit dem umschließenden Namespace beginnt) und stoppt dort.

Sie den Compiler, indem Sie den Namen von std:: in Rahmen mit einer using Richtlinie in Ihrem Namensraum helfen müssen:

namespace myNamespace 
{ 
    using std::sqrt 
    ... 
} 

Dann Standardüberladungsauflösung stattfinden, zu unterscheiden zwischen sqrt und std::sqrt, und wird Wählen Sie die korrekte sqrt Funktion, die aufgerufen werden soll.

jede Zweideutigkeit zu vermeiden, sollten Sie den Namen (std::sqrt oder myNamespace::sqrt)


Hinweise immer qualifizieren:

  • Wie von einfachen, Argument Dependent Lookup (ADL) für Namen std::sqrt zur Verfügung stellt Nachschlagen im ersten Fall (seit vector ist in std::), aber es ändert nicht das Problem, das Sie gegenüberstehen.

  • in std:: Ihre eigene sqrt Funktion Deklarieren ist eine sehr schlechte Idee (von der Norm verboten, mit Ausnahme der Vorlage Spezialisierungen)

+0

Gibt es eine Möglichkeit, alle std :: Namen in den aktuellen Namespace zu bringen? So etwas wie std :: *? – user2746401

+2

Es kümmert sich jedoch um die Parametertypen. Beim ersten Aufruf von 'sqrt' hat der Compiler über ADL sowohl' myNamespace :: sqrt' als auch 'std :: sqrt' gefunden (weil' vector' in 'std' steht). Es wählt nur "myNamespace :: sqrt", weil es besser passt. – Simple

+0

@Simple: guter Punkt, Anmerkung hinzugefügt – quantdev

2

Sie können über die Anweisung using std::sqrt; innerhalb myNamespacestd::sqrt in Ihren Namensraum bringen:

namespace myNamespace 
{ 
    vector<float> sqrt(vector<float> v) { return v; } 
    using std::sqrt; 
    ... 

Dann wird der Compiler die entsprechende sqrt in std::cout << sqrt(myFloat)

Verwandte Themen