문제

다음 코드가 있습니다.

#include <iostream>
#include <algorithm>
#include <map>
#include <iterator>

//namespace std
//{

std::ostream& operator << ( std::ostream& out, 
                const std::pair< size_t, size_t >& rhs )
{
    out << rhs.first << ", " << rhs.second;
    return out;
}
//}

int main() 
{

    std::map < size_t, size_t > some_map;

    // fill  some_map with random values
    for ( size_t i = 0; i < 10; ++i )
    {
        some_map[ rand() % 10 ] = rand() % 100;
    }

    // now I want to output this map
    std::copy( 
        some_map.begin(), 
        some_map.end(), 
        std::ostream_iterator< 
              std::pair< size_t, size_t > >( std::cout, "\n" ) );

    return 0;
}

이 코드에서는 출력 스트림에 대한 복사 맵을 원합니다. 이를 위해서는 연산자 정의가 필요합니다 << (..) - 확인. 그러나 이름을 찾는 규칙 컴파일러는 내 연산자 << ()를 찾을 수 없습니다.
std :: cout, std :: pair and std :: copy는 내 연산자를 불렀던 copy << - 모든 네임 스페이스 std에서.

빠른 솔루션 -STD 네임 스페이스에 내 OERATOR <<을 추가하십시오. 그러나 그것은 추악합니다.

이 문제에 대해 어떤 솔루션이나 해결 방법을 알고 있습니까?

도움이 되었습니까?

해결책 2

이 문제를 해결하기위한 새로운 우아한 방법을 설립했습니다.
답변을 읽을 때 많은 관심 아이디어가 있습니다.

  • transform std :: pair to std :: string을 위해 반복자를 랩합니다.
  • 랩 std :: 쌍, 오퍼레이터를 과부하 할 기회가 있습니다. << (...);
  • 인쇄 함수와 함께 일반적인 std :: for_each를 사용하십시오.
  • std :: for_each를 boost :: labda- std :: pair <> :: first and std :: pair <> :: Second Members;

다른 문제를 해결하기 위해 미래 에이 아이디어를 모두 사용할 것이라고 생각합니다.
그러나이 경우에 나는 BPROBLEM을 "지도의 데이터를 문자열로 변환하고 출력 스트림에 쓸 수있는"대신 "MAP의 데이터를 OUPUT 스트림에 복사"할 수 있음을 이해했습니다. 내 솔루션은 다음과 같습니다.

namespace
{
std::string toString( const std::pair< size_t, size_t >& data)
{
    std::ostringstream str;
    str << data.first << ", " << data.second;
    return str.str();
}
} // namespace anonymous

std::transform( 
    some_map.begin(), 
    some_map.end(), 
    std::ostream_iterator< std::string >( std::cout, "\n" ),
    toString );

이 방법은 다른 방법보다 가장 짧고 표현력이 있다고 생각합니다.

다른 팁

a std::pair 글쎄, 당신이 그것을 원하는 방법은 아마도 다음 사람이 원하는 방식과 다를 수 있습니다. 이것은 사용자 정의 functor 또는 lambda 함수의 좋은 사용 사례입니다. 그런 다음 논쟁으로 전달할 수 있습니다 std::for_each 일을하기 위해.

typedef std::map<size_t, size_t> MyMap;

template <class T>
struct PrintMyMap : public std::unary_function<T, void>
{
    std::ostream& os;
    PrintMyMap(std::ostream& strm) : os(strm) {}

    void operator()(const T& elem) const
    {
        os << elem.first << ", " << elem.second << "\n";
    }
}

코드 에서이 functor를 호출하려면 :

std::for_each(some_map.begin(),
              some_map.end(),
              PrintMyMap<MyMap::value_type>(std::cout));

C ++ 표준에 따라 STD :: 네임 스페이스에 물건을 추가하는 것이 불법이라고 지적하고 싶습니다 (섹션 17.4.3.1 참조).

당신이 원하는 것은 변형 반복자입니다. 이런 종류의 반복자는 다른 반복기를 감싸고, Operator ++ 및 Operator ==와 같은 모든 포지셔닝 메소드를 전달하지만 운영자* 및 연산자->를 재정의합니다.

빠른 스케치 :

template <typename ITER> 
struct transformingIterator : private ITER {
    transformingIterator(ITER const& base) : ITER(base) {}
    transformingIterator& operator++() { ITER::operator++(); return *this; }
    std::string operator*() const
    {
        ITER::value_type const& v = ITER::operator*();
        return "[" + v->first +", " + v->second + "]";
    }
...

방금 지나가지만 이것은 나를 위해 일을했기 때문에 다른 사람에게는 할 수 있습니다 (컷 버전) :

template<typename First, typename Second>
struct first_of {
    First& operator()(std::pair<First, Second>& v) const {
        return v.first;
    }
};

주어진 유스 케이스 :

transform (v.begin (), v.end (), 
           ostream_iterator<int>(cout, "\n"), first_of<int, string> ());

Boost Lambda를 사용하면 이와 같은 것을 시도 할 수 있습니다. Boost Lambda의 버전은 실제로 작동하지 않으며 나중에 테스트하고 수정하겠습니다.

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

using namespace boost::lambda;

std::for_each( some_map.begin(), some_map.end(), 
               std::cout << bind( &std::map<size_t,size_t>::value_type::first, _1 )
                         << ","
                         << bind( &std::map<size_t,size_t>::value_type::second, _1 ) );

이 답변을 삭제하고 싶지만 누군가가 토론을 흥미롭게 찾을 경우 지금 떠날 것입니다.

STD 라이브러리의 합리적인 확장이므로 STD 네임 스페이스에 넣었습니다. 다른 곳이 다른 곳에서 같은 일을하는 경우 링커 오류가 발생하지 않도록 정적으로 선언 할 수 있습니다.

떠오르는 또 다른 해결책은 std :: pair를위한 래퍼를 만드는 것입니다.

template<class A, class B>
struct pairWrapper {
  const std::pair<A,B> & x;
  pairWrapper(const std::pair<A,B> & x) : x(x) {}
}

template<class A,class B>
std::ostream & operator<<(std::ostream & stream, const pairWrapper<A,B> & pw) { ... }
    for (const auto& your_pair : your_container)
        your_stream << "[" << your_pair.first << "," << your_pair.second << "]" << endl;

더 단순하고 보편적입니다!

 for_each(some_map.begin(), some_map.end(), [](const std::map < size_t, size_t >::value_type &ite){
             cout<<ite.first<<" "<<ite.second<<endl;

}); 

--- C ++ 11에서는 괜찮습니다

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