الأمراض المنقولة جنسيا::نسخ إلى std::cout من أجل std::زوج

StackOverflow https://stackoverflow.com/questions/634087

سؤال

لدي التعليمات البرمجية التالية:

#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::زوج std::نسخة مما يسمى بلدي المشغل<< - كل من مساحة الأمراض المنقولة جنسيا.

حل سريع - إضافة بلدي oerator<< إلى مساحة الأمراض المنقولة جنسيا - ولكن هو قبيح ، imho.

ما هي الحلول أو الحل لهذه المشكلة هل تعرف ؟

هل كانت مفيدة؟

المحلول 2

لقد أسس جديدة أنيقة طريقة لحل هذه المشكلة.
لقد حصلت على الكثير من الاهتمام الأفكار عند قراءة الإجابات:

  • التفاف مكرر ، من أجل تحويل std::الزوج std::string;
  • التفاف std::زوج ، فرصة الزائد المشغل<<(...);
  • استخدام المعتاد std::for_each مع الطباعة functor;
  • استخدام std::for_each مع دفعة::labda - تبدو لطيفة ، باستثناء الوصول إلى std::زوج< >::أول std::زوج< >::الثانية أعضاء ؛

أعتقد أنني سوف تستخدم كل هذه الأفكار في المستقبل من أجل حل مختلف المشاكل الأخرى.
ولكن هذه الحالة لقد understaded أنني يمكن وضع بلدي bproblem باسم "تحويل خريطة بيانات السلاسل و تكتب لهم إلى دفق إخراج" بدلا من "نسخ خريطة البيانات 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 );

أعتقد أن هذا الأسلوب هو الأكثر قصيرة و معبرة أكثر من غيرها.

نصائح أخرى

وليس هناك طريقة قياسية لcout على std::pair لأنه، أيضا، كيف تريد المطبوعة يختلف ربما عن طريق الرجل القادم يريد ذلك. هذه هي حالة الاستخدام الجيد لfunctor مخصص أو وظيفة امدا. يمكنك ثم تمرير ذلك كحجة ل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 القياسية (انظر القسم 17.4.3.1).

ما تريده هو مكرر المحولة. هذا النوع من مكرر يلتف مكرر آخر، إلى الأمام جميع طرق تحديد المواقع مثل مشغل ++ و== المشغل، ولكن يعيد المشغل والمشغل * ->

ورسم سريع:

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

وعن طريق تفعيل لامبدا، قد تتمكن من محاولة شيء من هذا القبيل. النسخة لدي من دفعة لامبدا، هذا لا يعمل فعلا، وأنا اختبار وإصلاح في وقت لاحق.

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

[I تفضل حذف هذه الإجابة، ولكن سأترك ذلك الآن، في حالة شخص يجد مناقشة مثيرة للاهتمام.]

<الإضراب> حيث أنها امتداد معقول للمكتبة الأمراض المنقولة جنسيا، كنت مجرد وضعها في مساحة الأمراض المنقولة جنسيا، خاصة إذا كان هذا هو الشيء مرة واحدة. يمكنك يعلن مجرد أنها ثابتة لمنعها من التسبب في أخطاء رابط، يجب أن شخص آخر القيام بنفس الشيء في مكان آخر.

والحل الآخر الذي يتبادر إلى الذهن هو لإنشاء مجمع للالأمراض المنقولة جنسيا :: الزوج:

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