我在Visual Studio 2008在C ++编程分配工作。我们与定义下列命名空间层次结构文件被提供的(名字都只是为了这个职位的缘故,我知道“命名空间XYZ命名空间”是多余的):

(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
      }
}

在MAIN-NAMESPACE内容一堆文件之间分割,并由于某种原因,我不理解的operator <<对置1和链表是完全的MAIN-NAMESPACE以外(但集和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

它定义为处于MAIN-NAMESPACE内的类。当我创建类的实例,并尝试打印一组设置,它告诉我,: 错误C2679:二进制 '<<':没有操作员发现这需要类型的右边的操作数 'const的MAIN-NAMESPACE :: POINTER-COLLECTIONS-NAMESPACE ::设置'(或没有可接受的转化率)

不过,如果我只写一个main()函数,并建立集A,填满它,并用它工作的操作符 - 。

任何想法是什么问题? (注:我尝试使用的任意组合,包括我能想到的)。

有帮助吗?

解决方案 2

行我这出。 jpalecek的大约有现有另算<<命名空间中的直觉是正确的(显然我忘了其注释掉)。

对于命名空间的查找规则第一次启动在函数调用的命名空间中的搜索和搜索了封闭的命名空间,直至全局命名空间(当时它的参数依赖查找,如果没有找到匹配)。但是,如果沿途发现一些匹配运算符<<,它停止不管的事实,在这些功能使用的类型可能是不相容的,因为这里对本案进行了搜索。

的解决方案是要么它包括到MAIN-NAMESPACE(其我不允许),或者从全局命名空间中包含“使用::运算<<”导入。

其他提示

奇怪 - 即使把与类型相关的免费功能,以不同的命名空间是一个不好的做法,全局命名空间的声明总是可见

我能想到的唯一的事情就是与MAIN-NAMESPACE同名该声明将阴影的一个全局命名空间 - 是不是有一个operator<<,可能是完全无关的类型,在MAIN-NAMESPACE?如果是这样,你应该可以解决,通过在using ::operator<< MAIN-NAMESPACE声明。例如:

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);
  }
}

尝试调用函数明确?

::operator<<( cout, myObj );

正如SoaBox指出的那样,尝试调用它明确。

有关您的信息,如果你想打电话给其一直隐藏在当前命名空间的全局函数::前面函数绕过本地函数和调用全局函数。

  

尝试调用函数明确?

     

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

是的,这确实工作!

  

它会试图找到f函数中   当前命名空间(在的地方   呼叫),或在封闭的命名空间   c1和c2类型(namespace1,   namespace2 :: namespace3),但它会   不要试图在其他命名空间   搜索范围。

让我们看看,如果我得到这个权利:调用操作<<从main()函数的原因是工作,因为我是在全局命名空间(因为是运营商<<)。 从我实现了类调用时,它失败的原因是因为类是在一个没有全局命名空间,并有在它没有变数,指出对全局命名空间的编译器。

OK的人问一个具体的例子,所以这里的代码的相关部分。 // Disclamer:在超薄万一有人从我的UNI看到这个,遇到它在提交文件,并决定我把它抄了什么的,我的学号是311670137

这是头文件Set.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;
    }

这对我的作品

#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);
}

<强> CORRECTION :下面的文本是基于与编译器的克++家族的经验。答案的评论后,我已经重读的标准(其中规定,ADL将在常规名称查找使用,并定期名字查找应该找到运营商<<)。我也试图与科莫编译器(最符合标准的编译器,我知道的),该符号被发现。这似乎与克(尝试版本3.3,4.1,4.3)的一个问题++

原来的答复:

搜索Koening查找。(技术上ADL:参数依赖查找)

简单的回答是,如果有下面的类:

namespace test {
    class A {};
}

流插入操作员应被定义为:

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

函数或运算符应当以相同的命名空间被定义为的,它需要一个参数。 (*)

当编译器发现一个函数调用,例如:

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

它会尝试找到的˚F的当前命名空间(在调用的地方)函数或在C1和C2类(namespace1,namespace2 :: namespace3)的封闭命名空间,但它不会尝试在搜索其它的命名空间。

(*)在这种情况下,你几乎限于的测试的命名空间,因为你是不允许的功能添加到std命名空间(仅模板特)。

原始讯息的完

即使作为评论之前这可能只是与编译器的一个问题,它是推荐的定义在相同的命名空间的类型本身用户定义的类型操作的所有自由函数常见的用法和

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top