overloading << for map and multimap simultaneously

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • ozizus

    overloading << for map and multimap simultaneously

    I overloaded operator << for STL map successfully:

    template <typename T1, typename T2ostream & operator << (ostream &
    o, map <T1,T2& m)
    {
    //code
    }

    the code works like a charm. Now, I want the same functionality for
    multimap. Since their interface is same for the problem at hand, I
    want to make collection name a template parameter like this:

    template <typename MAP, typename T1, typename T2ostream & operator
    << (ostream & o, MAP<T1,T2& m)
    {
    //code
    }

    The compiler errors like this: syntax error : missing ')' before '<'

    thx,
    ozi.

  • Victor Bazarov

    #2
    Re: overloading &lt;&lt; for map and multimap simultaneously

    ozizus wrote:
    I overloaded operator << for STL map successfully:
    >
    template <typename T1, typename T2ostream & operator << (ostream &
    o, map <T1,T2& m)
    {
    //code
    }
    >
    the code works like a charm. Now, I want the same functionality for
    multimap. Since their interface is same for the problem at hand, I
    want to make collection name a template parameter like this:
    >
    template <typename MAP, typename T1, typename T2ostream & operator
    << (ostream & o, MAP<T1,T2& m)
    {
    //code
    }
    >
    The compiler errors like this: syntax error : missing ')' before '<'
    The compiler cannot deduce all three from the argument you give.
    Besides, if 'MAP' is a template (as you imply by using the template
    syntax when declaring the second argument), then it's not a "typename"
    argument, it's a "template <class,classcla ss MAP" argument. Try

    template<templa te<class, classclass MAP, typename T1, typename T2>
    ostream& operator << (...

    but it is most likely not going to work. I recommend dropping the T1
    and T2 arguments and just do

    template<class MAPostream& operator <<( ostream& o, MAP const& m)

    (you do want to have the output object 'const', by the way).

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask


    Comment

    • Kai-Uwe Bux

      #3
      Re: overloading &lt;&lt; for map and multimap simultaneously

      ozizus wrote:
      I overloaded operator << for STL map successfully:
      >
      template <typename T1, typename T2ostream & operator << (ostream &
      o, map <T1,T2& m)
      {
      //code
      }
      >
      the code works like a charm. Now, I want the same functionality for
      multimap. Since their interface is same for the problem at hand, I
      want to make collection name a template parameter like this:
      >
      template <typename MAP, typename T1, typename T2ostream & operator
      << (ostream & o, MAP<T1,T2& m)
      {
      //code
      }
      >
      The compiler errors like this: syntax error : missing ')' before '<'
      a) technically, you want something like:

      template < template <class, class class MAP, typename T1, typename T2 >

      Read up on template template parameters (as opposed to typename template
      parameters).

      b) Using a template template parameter here, is a BadIdea(tm) since your
      template would match too many things, e.g., it would match a pair<S,T>. In
      that case, your code will not work.

      Thus: you should just do another template for multimaps.

      c) You may want to make your code aware of the Allocator and Comparison
      typename parameters in the map template. I.e.,

      template< typename S, typename T, typename A, typename C >
      std::ostream & operator<< ( std::ostream & ostr,
      const std::multimap< S, T, A, C & v );



      Best

      Kai-Uwe Bux

      Comment

      • terminator

        #4
        Re: overloading &lt;&lt; for map and multimap simultaneously

        On Jul 29, 4:00 pm, ozizus <o...@ce.yildiz .edu.trwrote:
        I overloaded operator << for STL map successfully:
        >
        template <typename T1, typename T2ostream & operator << (ostream &
        o, map <T1,T2& m)
        {
        //code
        >
        }
        >
        the code works like a charm. Now, I want the same functionality for
        multimap. Since their interface is same for the problem at hand, I
        want to make collection name a template parameter like this:
        >
        template <typename MAP, typename T1, typename T2ostream & operator
        << (ostream & o, MAP<T1,T2& m)
        {
        //code
        >
        }
        >
        The compiler errors like this: syntax error : missing ')' before '<'
        >
        thx,
        ozi.
        you can simply write:

        template<typena me MapT>
        ostream & operator << (ostream & o, const MapT& m){
        typedef typename MapT::Key_type T1;
        typedef typename MapT::mapped_ty pe T2;
        //code

        return o;
        };


        if your compiler supports concepts ,things will be easier :

        auto concept map_like <MapT>{//what a (multi)map looks like.
        typedef typename MapT::key_type key_type;
        typedef typename MapT::mapped_ty pe mapped_type;
        //etc:

        };

        template<map_li ke MapT>//argument type must behave like a map
        ostream & operator << (ostream & o, const MapT& m){
        //code

        return o;
        };


        regards,
        FM.

        Comment

        • ozizus

          #5
          Re: overloading &lt;&lt; for map and multimap simultaneously

          a) technically, you want something like:
          >
          template < template <class, class class MAP, typename T1, typename T2 >
          >
          Read up on template template parameters (as opposed to typename template
          parameters).
          I tried the code below, but got error C2065: 'T2' : undeclared
          identifier.

          template<templa te<class,classc lass MAP, typename T1, typename t2>
          ostream & operator << (ostream & o, MAP<T1,T2& m)

          C++ is huge, is not it, lots of reading up to do.. Thx anyway.

          Comment

          • ozizus

            #6
            Re: overloading &lt;&lt; for map and multimap simultaneously

            >
            template<typena me MapT>
            ostream & operator << (ostream & o, const MapT& m){
            typedef typename MapT::Key_type T1;
            typedef typename MapT::mapped_ty pe T2;
            //code
            >
            return o;
            >
            };
            >
            template<typena me MapTostream & operator << (ostream & o, MapT & m)
            {
            typedef typename MapT::key_type T1;
            typedef typename MapT::mapped_ty pe T2;
            ...
            }

            gives the cute one liner below:

            error LNK2019: unresolved external symbol "class
            std::basic_ostr eam<char,struct std::char_trait s<char & __cdecl
            operator<<<clas s std::vector<int ,class std::allocator< int,class
            std::map<class std::vector<int ,class std::allocator< int,int,struct
            std::less<class std::vector<int ,class std::allocator< int >,class
            std::allocator< struct std::pair<class std::vector<int ,class
            std::allocator< int const ,int (class
            std::basic_ostr eam<char,struct std::char_trait s<char &,class
            std::map<class std::vector<int ,class std::allocator< int,class
            std::map<class std::vector<int ,class std::allocator< int,int,struct
            std::less<class std::vector<int ,class std::allocator< int >,class
            std::allocator< struct std::pair<class std::vector<int ,class
            std::allocator< int const ,int >,struct std::less<class
            std::vector<int ,class std::allocator< int >,class
            std::allocator< struct std::pair<class std::vector<int ,class
            std::allocator< int const ,class std::map<class
            std::vector<int ,class std::allocator< int,int,struct std::less<class
            std::vector<int ,class std::allocator< int >,class
            std::allocator< struct std::pair<class std::vector<int ,class
            std::allocator< int const ,int &)" (??$?6V?$vector @HV?
            $allocator@H@st d@@@std@@V?$map @V?$vector@HV?$ allocator@H@std @@@std@@HU?
            $less@V?$vector @HV?$allocator@ H@std@@@std@@@2 @V?$allocator@U ?$pair@$
            $CBV?$vector@HV ?$allocator@H@s td@@@std@@H@std @@@2@@1@@@YAAAV ?
            $basic_ostream@ DU?$char_traits @D@std@@@std@@A AV01@AAV?$map@V ?
            $vector@HV?$all ocator@H@std@@@ std@@V?$map@V?$ vector@HV?
            $allocator@H@st d@@@std@@HU?$le ss@V?$vector@HV ?
            $allocator@H@st d@@@std@@@2@V?$ allocator@U?$pa ir@$$CBV?$vecto r@HV?
            $allocator@H@st d@@@std@@H@std@ @@2@@2@U?$less@ V?$vector@HV?
            $allocator@H@st d@@@std@@@2@V?$ allocator@U?$pa ir@$$CBV?$vecto r@HV?
            $allocator@H@st d@@@std@@V?$map @V?$vector@HV?$ allocator@H@std @@@std@@HU?
            $less@V?$vector @HV?$allocator@ H@std@@@std@@@2 @V?$allocator@U ?$pair@$
            $CBV?$vector@HV ?$allocator@H@s td@@@std@@H@std @@@2@@2@@std@@@ 2@@1@@Z)
            referenced in function _main


            MSVS2005, seems like no concepts. Thx anyway.


            Comment

            • Kai-Uwe Bux

              #7
              Re: overloading &lt;&lt; for map and multimap simultaneously

              ozizus wrote:
              >
              >a) technically, you want something like:
              >>
              > template < template <class, class class MAP, typename T1, typename T2
              > >
              >>
              >Read up on template template parameters (as opposed to typename template
              >parameters).
              >
              I tried the code below, but got error C2065: 'T2' : undeclared
              identifier.
              You have a typo:
              template<templa te<class,classc lass MAP, typename T1, typename t2>
              ^^
              ostream & operator << (ostream & o, MAP<T1,T2& m)
              ^^


              Also: make that a MAP<T1,T2const & m.
              ^^^^^

              Also: don't do this anyway. I already explained why it is a bad idea.

              If you want to avoid code duplication, implement a template

              template < typename Cont >
              std::ostream & write_sequence ( std::ostream & os, Cont const & c )

              and use it to implement output for map and multimap.

              C++ is huge, is not it, lots of reading up to do.. Thx anyway.
              True.


              Best

              Kai-Uwe Bux

              Comment

              • James Kanze

                #8
                Re: overloading &lt;&lt; for map and multimap simultaneously

                On Jul 29, 3:00 pm, ozizus <o...@ce.yildiz .edu.trwrote:
                I overloaded operator << for STL map successfully:
                template <typename T1, typename T2ostream & operator << (ostream &
                o, map <T1,T2& m)
                {
                //code
                }
                the code works like a charm.
                Are you sure? In what namespace did you put it? If you put it
                in std, then you have undefined behavior. And if you put it in
                some other namespace, if you use it in a template, the compiler
                will only find it when it is instantiated on a class in the same
                namespace (dependant name look-up oblige).

                In general, you can't reliably overload operator<< generically
                for any of the container types in the standard library (nor can
                you overload it for instantiations where only standard types are
                involved). In general, of course, you don't want to either.

                --
                James Kanze (Gabi Software) email: james.kanze@gma il.com
                Conseils en informatique orientée objet/
                Beratung in objektorientier ter Datenverarbeitu ng
                9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                Comment

                • ozizus

                  #9
                  Re: overloading &lt;&lt; for map and multimap simultaneously

                  On Jul 29, 10:34 pm, James Kanze <james.ka...@gm ail.comwrote:
                  On Jul 29, 3:00 pm, ozizus <o...@ce.yildiz .edu.trwrote:
                  >
                  I overloaded operator << for STL map successfully:
                  template <typename T1, typename T2ostream & operator << (ostream &
                  o, map <T1,T2& m)
                  {
                  //code
                  }
                  the code works like a charm.
                  >
                  Are you sure? In what namespace did you put it?
                  I put it in no namespace. I use "using namespace std;". This may be
                  bad practice but it works. Since I overloaded << for other containers,
                  I can output any object that is a combination of these containers in
                  one line. Same is true for >too.

                  eg.
                  map<vector<int> , set<string>m;
                  //code
                  cout<<m;

                  very powerfull.

                  Comment

                  • terminator

                    #10
                    Re: overloading &lt;&lt; for map and multimap simultaneously

                    On Jul 29, 6:28 pm, ozizus <o...@ce.yildiz .edu.trwrote:
                    template<typena me MapT>
                    ostream & operator << (ostream & o, const MapT& m){
                    typedef typename MapT::Key_type T1;
                    typedef typename MapT::mapped_ty pe T2;
                    //code
                    >
                    return o;
                    >
                    };
                    >
                    template<typena me MapTostream & operator << (ostream & o, MapT & m)
                    {
                    typedef typename MapT::key_type T1;
                    typedef typename MapT::mapped_ty pe T2;
                    ..
                    >
                    }
                    >
                    gives the cute one liner below:
                    >
                    error LNK2019: unresolved external symbol "class
                    std::basic_ostr eam<char,struct std::char_trait s<char & __cdecl
                    operator<<<clas s std::vector<int ,class std::allocator< int,class
                    std::map<class std::vector<int ,class std::allocator< int,int,struct
                    std::less<class std::vector<int ,class std::allocator< int >,class
                    std::allocator< struct std::pair<class std::vector<int ,class
                    std::allocator< int const ,int (class
                    std::basic_ostr eam<char,struct std::char_trait s<char &,class
                    std::map<class std::vector<int ,class std::allocator< int,class
                    std::map<class std::vector<int ,class std::allocator< int,int,struct
                    std::less<class std::vector<int ,class std::allocator< int >,class
                    std::allocator< struct std::pair<class std::vector<int ,class
                    std::allocator< int const ,int >,struct std::less<class
                    std::vector<int ,class std::allocator< int >,class
                    std::allocator< struct std::pair<class std::vector<int ,class
                    std::allocator< int const ,class std::map<class
                    std::vector<int ,class std::allocator< int,int,struct std::less<class
                    std::vector<int ,class std::allocator< int >,class
                    std::allocator< struct std::pair<class std::vector<int ,class
                    std::allocator< int const ,int &)" (??$?6V?$vector @HV?
                    $allocator@H@st d@@@std@@V?$map @V?$vector@HV?$ allocator@H@std @@@std@@HU?
                    $less@V?$vector @HV?$allocator@ H@std@@@std@@@2 @V?$allocator@U ?$pair@$
                    $CBV?$vector@HV ?$allocator@H@s td@@@std@@H@std @@@2@@1@@@YAAAV ?
                    $basic_ostream@ DU?$char_traits @D@std@@@std@@A AV01@AAV?$map@V ?
                    $vector@HV?$all ocator@H@std@@@ std@@V?$map@V?$ vector@HV?
                    $allocator@H@st d@@@std@@HU?$le ss@V?$vector@HV ?
                    $allocator@H@st d@@@std@@@2@V?$ allocator@U?$pa ir@$$CBV?$vecto r@HV?
                    $allocator@H@st d@@@std@@H@std@ @@2@@2@U?$less@ V?$vector@HV?
                    $allocator@H@st d@@@std@@@2@V?$ allocator@U?$pa ir@$$CBV?$vecto r@HV?
                    $allocator@H@st d@@@std@@V?$map @V?$vector@HV?$ allocator@H@std @@@std@@HU?
                    $less@V?$vector @HV?$allocator@ H@std@@@std@@@2 @V?$allocator@U ?$pair@$
                    $CBV?$vector@HV ?$allocator@H@s td@@@std@@H@std @@@2@@2@@std@@@ 2@@1@@Z)
                    referenced in function _main
                    >
                    That looks like a multiple definition error.try defining some
                    function :

                    ostream& out(mytype& m,ostream& os);
                    MSVS2005, seems like no concepts. Thx anyway.
                    no surprize it is too new and for ms2005.

                    MSVC supports templates as arguments but I did not want to suggest
                    that.As long as (multi)map takes 4 type arguments(last two have
                    default params) you will need five arguments for such a template:

                    #define T typename
                    template< template <T,T,T,TT MapT/*0*/,T Key/*1*/, T Value/*2*/,T
                    Predicate/*3*/,T Alloc/*4*/>
                    ostream& (ostream& os, MapT<Key,Value, Predicate,Alloc & m);

                    on MSVS (multi)map/set derive from 'template<typen ame traitsstruct
                    _Tree' defined in <xtreeheader.yo u can overload for '_Tree' but that
                    affects (multi)set as well(potentiall y more classes):

                    #include<xtree>
                    using namespace std;
                    template <typename traits>
                    ostream& (ostream& os, _Tree<traits& m);

                    regards,
                    FM.

                    Comment

                    • James Kanze

                      #11
                      Re: overloading &lt;&lt; for map and multimap simultaneously

                      On Jul 30, 12:39 pm, ozizus <o...@ce.yildiz .edu.trwrote:
                      On Jul 29, 10:34 pm, James Kanze <james.ka...@gm ail.comwrote:
                      On Jul 29, 3:00 pm, ozizus <o...@ce.yildiz .edu.trwrote:
                      I overloaded operator << for STL map successfully:
                      template <typename T1, typename T2ostream & operator << (ostream &
                      o, map <T1,T2& m)
                      {
                      //code
                      }
                      the code works like a charm.
                      Are you sure? In what namespace did you put it?
                      I put it in no namespace. I use "using namespace std;". This may be
                      bad practice but it works.
                      No it doesn't. (I mean putting your operator in no namespace.)
                      Try something like:

                      std::copy(
                      c.begin(), c.end(),
                      std::ostream_it erator< std::map< X, Y ( std::cout,
                      "\n" ) ) ;

                      Your operator won't be found, unless either X or Y are user
                      defined types in the same namespace as your operator.
                      Since I overloaded << for other containers,
                      I can output any object that is a combination of these containers in
                      one line. Same is true for >too.
                      eg.
                      map<vector<int> , set<string>m;
                      //code
                      cout<<m;
                      very powerfull.
                      Very unmaintainable, you mean. Not something you really want to
                      do; it's a definite recepe for undefined behavior.

                      The answer to your question is simple: there's no way to define
                      an overload of operator<< for a standard type in a way that is
                      guaranteed to work in all cases, and you don't want to, even if
                      you could.

                      --
                      James Kanze (GABI Software) email:james.kan ze@gmail.com
                      Conseils en informatique orientée objet/
                      Beratung in objektorientier ter Datenverarbeitu ng
                      9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                      Comment

                      Working...