2009-01-29 70 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); 
} 
相关问题