2009-01-29 282 views
2

我正在Visual Studio 2008中進行C++編程任務。我們與定義下列命名空間層次結構的文件中提供的(名字都只是爲了這個職位的緣故,我知道「命名空間XYZ命名空間」是多餘的):C++編譯器無法找到函數(名稱空間相關)

(MAIN-NAMESPACE){ 

     a bunch of functions/classes I need to implement... 

     (EXCEPTIONS-NAMESPACE){ 

      a bunch of exceptions 
     } 

     (POINTER-COLLECTIONS-NAMESPACE){ 

      Set and LinkedList classes, plus iterators 
     } 
} 

主NAMESPACE內容之間的分裂一堆文件,由於某些原因,我不明白運營商< < Set和LinkedList完全在MAIN-NAMESPACE之外(但在Set和LinkedList的頭文件中)。 這裏是集版本:

template<typename T> 
std::ostream& operator<<(std::ostream& os, 
         const MAIN-NAMESPACE::POINTER-COLLECTIONS-NAMESPACE::Set<T>& set) 

現在,這裏的問題:我有以下數據結構:

Set A 
Set B 
Set C 
double num 

它定義爲在主命名空間中的類。當我創建該類的一個實例並嘗試打印其中一個集合時,它告訴我: 錯誤C2679:二進制'< <':找不到操作符,其類型爲'const'的右手操作數MAIN-NAMESPACE :: POINTER-COLLECTIONS-NAMESPACE :: Set'(或者沒有可接受的轉換)

但是,如果我只寫一個main()函數,並創建Set A,填充它並使用operator- it作品。

任何想法是什麼問題? (注意:我嘗試過使用和包含我能想到的任何組合)。

+0

如果您可以創建一個小而完整的示例來展示問題,以便您可以發佈所有代碼,那麼找到答案會更容易。只要你給的細節,可能會有很多錯誤。 – 2009-01-30 00:12:43

+0

也許如果你粘貼導致錯誤的代碼... – SoapBox 2009-01-30 00:22:19

回答

2

好的我想通了。 jpalecek關於在命名空間中存在另一個運算符< <的直覺是正確的(顯然,我忘了將它註釋掉)。

命名空間的查找規則首先在函數調用的命名空間中開始搜索,然後搜索封閉的命名空間,直到全局命名空間(如果沒有找到匹配,則執行依賴於參數的查找)。但是,如果沿途找到與運營商< <匹配的某個匹配項,它將停止搜索,而不管這些函數中使用的類型可能不兼容(如此處所述)。

該解決方案要麼將其包含到MAIN-NAMESPACE(我不允許)中,要麼使用「using :: operator < <」從全局名稱空間導入它。

0

請嘗試明確調用該函數?

::operator<<(cout, myObj); 
0

正如SoaBox指出的那樣,嘗試明確地調用它。

爲了您的信息,如果您希望調用一個隱藏在當前命名空間中的全局函數,那麼使用::來繞過本地函數並調用全局函數。

0

更正:下面的文本是基於g ++系列編譯器的經驗。在對答案的評論之後,我重新閱讀了標準(其中規定ADL將用於常規名稱查找,常規名稱查找應找到運營商< <)。我也嘗試了comeau編譯器(我知道的最標準的兼容編譯器)並找到了符號。這似乎是與g ++(嘗試版本3.3,4.1,4.3)的問題。

原來的答覆:

搜索Koening查找(ADL技術:參數依賴查找)。

簡短的回答是,如果你有下面的類:

namespace test { 
    std::ostream& operator<<(std::ostream&, A const &); 
} 

職能或經營者應當在相同的命名空間中定義:

namespace test { 
    class A {}; 
} 

流插入運營商應定義它需要的一個論據。(*)

當編譯器發現一個函數調用,如:

namespace test2 { 
    void g() { 
     namespace1::class1 c1; 
     namespace2::namespace3::class2 c2; 
     f(c1, c2); 
    } 
} 

它會試圖找到在當前命名空間中的˚F功能(在調用的地方),或在封閉的命名空間c1和c2類型(namespace1,namespace2 :: namespace3),但它不會在搜索中嘗試其他名稱空間。 (*)在這種情況下,由於不允許將函數添加到std名稱空間(僅限模板專用化),因此在這種情況下,您幾乎侷限於測試名稱空間。

末原崗位的。

即使作爲評論之前這可能只是與編譯器有問題,這是常見的用法,並建議定義在相同的命名空間的類型本身就是一個用戶定義類型操作全部免費的功能。

+0

是的,但是對於當前的名稱空間,它也會搜索其封閉的名稱空間(通常)。 – jpalecek 2009-01-30 00:49:32

2

奇怪 - 即使把一個類型不同的命名空間相關聯的免費功能是一個不好的做法,全局命名空間的聲明總是可見。

我能想到的唯一的事情就是與MAIN-NAMESPACE相同的名稱將陰影的一個全局命名空間的聲明 - 是不是有operator<<,可能是完全無關的類型,在MAIN-NAMESPACE?如果是這樣,您應該在MAIN-NAMESPACE中通過using ::operator<<聲明修復該問題。例如:

namespace A 
{ 
namespace B 
{ 
    class C{}; 
} 

} 

void f(A::B::C*); 

namespace A 
{ 
    void f(int*); // try commenting 
    using ::f; // these two lines 
    void g() 
    { 
    B::C* c; 
    f(c); 
    } 
} 
+0

運算符<<僅在這兩個文件中:一個用於Set,另一個用於LinkedList。主命名空間之外。 – 2009-01-30 01:08:55

0

嘗試調用該函數明確?

::運算< <(COUT,MyObj中);

是的,這的確行得通!

它會試圖找到f函數在 當前的命名空間(在 調用的地方),或在C1和C2類(namespace1, namespace2 :: namespace3)的封閉命名空間 ,但它將 不會嘗試在 搜索其他命名空間。

讓我們看看,如果我得到這個權利:之所以從main()函數調用操作< <工作是因爲我是在全局命名空間(因爲是運營商< <)。 從我實現的類調用時失敗的原因是因爲該類位於非全局名稱空間中,並且其中沒有指向編譯器指向全局名稱空間的變量。

+0

並非如此,來自任何名稱空間的聲明在子名稱空間中都是可見的,即。來自全局名稱空間的聲明在任何地方都可見(通過非ADL查找)。它不工作的原因必須在別處。 – jpalecek 2009-01-30 00:55:43

0

好的人問了一個具體的例子,所以這裏是代碼的相關部分。 // Disclamer:在渺茫的情況下,有人從我的uni看到這件事,在提交文件中遇到它,並決定我複製它或什麼,我的學號是311670137

這是頭文件集。H:

namespace MTM {//This is the MAIN-NAMESPACE 

    namespace PointerCollections { 

     (ITERATORS AND PREDICATE CLASSES) 

     template<typename T> 
     class Set { 
     public: 

     ///////////////////////////////// 
     // Definitions 
     ///////////////////////////////// 

     private: 

     ///////////////////////////////// 
     // Definitions 
     ///////////////////////////////// 

     }; 


/////////////////////////////////////////////////////////////////////////////// 
// The implementation part. 
/////////////////////////////////////////////////////////////////////////////// 
     } 
} 
// operator<< - the same a Set::print(std::ostream& os, 
//         const BinaryPredicate<T>& predicate) 
// function called with the 'predicate' parameter omitted 
template<typename T> 
std::ostream& operator<<(std::ostream& os, 
         const MTM::PointerCollections::Set<T>& set){ 

    set.print(os); 
    return os; 
} 

這是我在不同的文件中定義:

namespace MTM { 
    using std::ostream; 

    class Schedule { 
    public: 
     /////////////////// 
     //Definitions, including: 
     /////////////////// 
    void registerStation(string stationName); 
    void reportRegisteredStations(std::ostream& outputStream) const; 

    private:  //My database 
       //All the classes Set recieves are defined elsewhere 
     Set<RegisteredStation> places; 
     Set<BusLine> busses; 
     Set<TrainLine> trains; 
     double tarifForBuses; 
     double tarifForTrains; 
    }; 

} 

而且這裏距離是最主要的:

Schedule s(); 
s.registerStation("1"); 
s.reportRegisteredStations(cout);//This invokes the error. Definition follows: 

reportRegisteredStations被定義爲:

void Schedule::reportRegisteredStations(std::ostream& outputStream) const{ 

     outputStream<<places; 
    } 
0

這適用於我

#include <iostream> 
#include <string> 
using std::string; 

    namespace MTM {//This is the MAIN-NAMESPACE 

    namespace PointerCollections { 

     template<typename T> 
     class Set { 
     }; 


     } 
} 
template<typename T> 
std::ostream& operator<<(std::ostream& os, 
         const MTM::PointerCollections::Set<T>& set){ 

    return os; 
} 

namespace MTM { 
    using std::ostream; 
    using PointerCollections::Set; 
    class Schedule { 
    public: 
     /////////////////// 
     //Definitions, including: 
     /////////////////// 
    void registerStation(string stationName); 
    void reportRegisteredStations(std::ostream& outputStream) const; 

    private:  //My database 
       //All the classes Set recieves are defined elsewhere 
     Set<int> places; 
     Set<int> busses; 
     Set<int> trains; 
     double tarifForBuses; 
     double tarifForTrains; 
    }; 
void Schedule::reportRegisteredStations(std::ostream& outputStream) const{ 

     outputStream<<places; 
    } 

} 

int main() 
{ 
    MTM::Schedule s; 
    s.reportRegisteredStations(std::cout); 
} 
相關問題