std::copy to std:: cout for std:: pair

Mam następny kod:

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

W tym kodzie chcę tylko skopiować mapę do strumienia wyjściowego. W tym celu muszę zdefiniować operator Ponieważ std:: cout, STD:: pair i STD:: copy wywołały mojego operatora

Szybkie rozwiązanie-dodaj mój oerator

Jakie rozwiązania lub obejście tego problemu znasz?

Author: Serge, 2009-03-11

10 answers

Nie ma standardowego sposobu na wydrukowanie std::pair ponieważ, cóż, sposób, w jaki chcesz to wydrukować, prawdopodobnie różni się od sposobu, w jaki następny facet chce to zrobić. Jest to dobry przypadek użycia dla niestandardowego functora lub funkcji lambda. Następnie możesz przekazać to jako argument std::for_each, aby wykonać pracę.

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

Aby wywołać ten funktor z twojego kodu:

std::for_each(some_map.begin(),
              some_map.end(),
              PrintMyMap<MyMap::value_type>(std::cout));
 16
Author: Michael Kristofik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-11 13:10:42

Wymyśliłem nowy, elegancki sposób na rozwiązanie tego problemu.
Mam wiele ciekawych pomysłów, gdy czytam odpowiedzi:

  • wrap iterator, dla przekształcenia std:: pair na std:: string;
  • wrap std:: para, bo masz szansę przeciążyć operatora
  • użyj zwykłej STD:: for_each z funkcją printing;
  • użyj std::for_each z boost::labda - wygląda ładnie, z wyjątkiem dostępu do STD::pair:: first I STD:: pair:: second członkowie;

Myślę, że wykorzystam wszystkie te pomysły w przyszłości do rozwiązywania różnych innych problemów.
Ale w tym przypadku mam zaniżone, że mogę sformułować mój bproblem jako "przekształcić dane mapy do ciągów i zapisać je do strumienia wyjściowego "zamiast" skopiować dane mapy do strumienia ouput". Moje rozwiązanie wygląda tak:

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 );
Myślę, że ta metoda jest najbardziej krótka i wyrazista niż inne.
 16
Author: bayda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-14 19:05:54

Chciałbym tylko zaznaczyć, że dodawanie rzeczy do przestrzeni nazw std:: jest nielegalne zgodnie ze standardem C++ (patrz sekcja 17.4.3.1).

 10
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-11 11:19:37

Chcesz transformującego iteratora. Ten rodzaj iteratora otacza inny iterator, przekazując wszystkie metody pozycjonowania, takie jak operator++ i operator==, ale redefiniuje operator* i operator ->.

Szybki szkic:

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 + "]";
    }
...
 5
Author: MSalters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-11 12:28:40

Tylko przechodziłem, ale to mi się udało, więc może komuś innemu (wersja wycięta):

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

Podany przypadek użycia:

transform (v.begin (), v.end (), 
           ostream_iterator<int>(cout, "\n"), first_of<int, string> ());
 4
Author: Rado,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-21 15:27:05

Używając Boost Lambda, możesz spróbować czegoś takiego. Wersja mam Boost Lambda, to faktycznie nie działa, będę testować i naprawić później.

#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 ) );
 2
Author: paxos1977,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-11 14:07:44

[wolałbym usunąć tę odpowiedź, ale na razie ją zostawię, na wypadek gdyby ktoś uznał dyskusję za interesującą.]

ponieważ jest to rozsądne rozszerzenie biblioteki std, po prostu umieściłbym je w przestrzeni nazw std, zwłaszcza jeśli jest to jednorazowa rzecz. Możesz po prostu zadeklarować, że jest statyczny, aby zapobiec powodowaniu błędów linkera, jeśli ktoś inny zrobi to samo gdzieś indziej.

Innym rozwiązaniem, które przychodzi na myśl, jest stworzenie wrappera dla 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) { ... }
 2
Author: TrayMan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-11 15:27:47
    for (const auto& your_pair : your_container)
        your_stream << "[" << your_pair.first << "," << your_pair.second << "]" << endl;
Bardziej proste i uniwersalne !
 1
Author: Dominique,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-18 16:07:29
 for_each(some_map.begin(), some_map.end(), [](const std::map < size_t, size_t >::value_type &ite){
             cout<<ite.first<<" "<<ite.second<<endl;

}); 

- - - jest dobrze z C++11

 0
Author: user3762106,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-26 19:50:47

Oto adapter do użycia z std::copy i std::ostream_iterator dla typu std::pair. Kończy się to trzymaniem jednego dodatkowego odniesienia, ale optymalizacja kompilatora może się tym zająć. BTW, pierwszy typ w std::pair z std::map::value_type będzie const.

template <typename pair_type>
class pair_adaptor
{
public:
    const pair_type &m;
    pair_adaptor(const pair_type &a) : m(a) {}

    friend std::ostream &operator << (std::ostream &out, 
        const pair_adaptor <pair_type> &d)
    {
        const pair_type &m = d.m;
        return out << m.first << " => " << m.second;
    }
};

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

std::copy (mymap.begin(), mymap.end(),
    std::ostream_iterator < 
        pair_adaptor <value_type> > (std::cout, "\n"));

std::copy (mymap.begin(), mymap.end(),
    std::ostream_iterator < 
        pair_adaptor <
            std::pair<const size_t, size_t>>> (std::cout, "\n"));
 0
Author: kisa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-23 10:14:59