문제

C ++ 프로그래밍 할당에 대해 Visual Studio 2008에서 일하고 있습니다. 우리는 다음 네임 스페이스 계층 구조를 정의하는 파일이 제공되었습니다 (이름은이 게시물을 위해서만 가능합니다. "네임 스페이스 xyz-namespace"가 중복된다는 것을 알고 있습니다).

(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 내용은 많은 파일로 분할되며 어떤 이유로 든 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

Main-Namespace 내에서 클래스에 정의되어 있습니다. 클래스의 인스턴스를 생성하고 세트 중 하나를 인쇄하려고하면 다음과 같이 알려줍니다. 오류 C2679 : BAINSE '<<': 오른쪽의 오른쪽 피연산자 'const main-namespace : : pointer-collections-namespace :: set '(또는 허용 가능한 변환이 없음)

그러나 main () 함수를 작성하고 세트 a를 작성하고 채우고 작업자를 사용하는 경우 작동합니다.

문제가 무엇인지 아십니까? (참고 : 사용의 조합을 시도했으며 생각할 수있는 포함).

도움이 되었습니까?

해결책 2

알았어 나는 이것을 알아 냈다. 기존의 다른 연산자 << 네임 스페이스에 대한 JPalecek의 직관은 정확했습니다 (분명히 댓글을 달리는 것을 잊었습니다).

네임 스페이스의 조회 규칙은 먼저 함수 호출의 네임 스페이스에서 검색을 시작하고 전역 네임 스페이스에 이르기까지 동봉 네임 스페이스를 검색합니다 (그런 다음 일치하지 않으면 인수 종속 조회를 수행합니다). 그러나, 운영자 <<과 일치하는 방식으로, 해당 함수에 사용 된 유형이 여기서와 같이 호환되지 않을 수 있다는 사실에 관계없이 검색을 중지합니다.

솔루션은이를 메인 이름 공간에 포함 시키거나 (허용되지 않음) "사용 :: Operator <<"을 사용하여 글로벌 네임 스페이스에서 가져 오는 것입니다.

다른 팁

이상한 - 유형과 관련된 무료 기능을 다른 네임 스페이스에 넣는 것은 나쁜 관행이지만, 글로벌 네임 스페이스 선언은 항상 보입니다.

내가 생각할 수있는 유일한 것은 같은 이름을 가진 선언입니다. 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);

예, 그게 작동합니다!

현재 네임 스페이스 (통화 장소에서) 또는 C1 및 C2 유형 (네임 스페이스 1, 네임 스페이스 2 :: 네임 스페이스 3)에서 F 함수를 찾으려고하지만 검색에서 다른 네임 스페이스를 시도하지 않습니다.

그래서 내가 이것을 제대로 얻었는지 보자. 내가 구현 한 클래스에서 호출 할 때 실패한 이유는 클래스가 글로벌 네임 스페이스가 아니고 컴파일러가 글로벌 네임 스페이스를 향한 변수가 없었기 때문입니다.

OK 사람들은 구체적인 예제를 요청 했으므로 코드의 관련 부분이 있습니다. // disclamer : Slim Case에서 내 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;
    }

이것은 나를 위해 작동합니다

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

보정: 아래 텍스트는 G ++ 컴파일러 제품군에 대한 경험을 기반으로합니다. 답변에 대한 의견 후에는 표준을 다시 읽었습니다 (ADL은 일반 이름 조회를 통해 ADL이 사용될 것이며 일반 이름 조회는 연산자 <<)를 찾아야합니다. 나는 또한 함께 시도했다 comeau 컴파일러 (내가 알고있는 가장 표준 호환 컴파일러) 및 기호가 발견됩니다. G ++의 문제인 것 같습니다 (시도 된 버전 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 );
   }
}

그것은 그것을 찾으려고 노력할 것입니다 에프 현재 네임 스페이스 (통화 장소에서) 또는 C1 및 C2 유형의 네임 스페이스 (네임 스페이스 1, 네임 스페이스 2 :: 네임 스페이스 3)에서 기능하지만 검색에서 다른 네임 스페이스를 시도하지는 않습니다.

(*)이 경우, 당신은 테스트 네임 스페이스, STD 네임 스페이스에 함수를 추가 할 수 없으므로 (템플릿 전문화 만).

원래 게시물의 끝.

이전에 댓글을 달았음에도 불구하고 컴파일러에 문제가 될 수 있지만 일반적인 사용법이며 유형 자체와 동일한 네임 스페이스에서 사용자 정의 된 유형에서 작동하는 모든 자유 함수를 정의하는 것이 좋습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top