using two strings values as a key to the map

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

    using two strings values as a key to the map

    I need to be able to map two string to some value in the map. I
    consider two alternatives to implement : using pair class or using a
    separate class/struct containing two member strings. I prefer the
    latter for it's more descriptive. However, in the latter
    implementation (equivalent of which is shown below), I got some
    compiler errors on gcc 3.3.1 with MyClass.


    #include<map>
    #include <string>

    using namespace std;

    struct MyClass
    {
    MyClass ( const string &a, const string & b):a_(a),b_(b){ }
    string a_;
    string b_;
    };

    inline bool operator <(const MyClass &a, const MyClass & b)
    {
    return a.a_<b.a_ ||(a.a_==b.a_?a .b_<b.b_:false) ;
    }
    int main()
    {
    //This caused the error
    map<MyClass, MyClass *>m;
    MyClass my("Foo", "Bar");
    m.find(my);

    //This fixed it
    map<MyClass, MyClass *>m1;
    m1.find(MyClass ("Foo","Bar" ));
    }

    Unfortunately, I can't show the compiler error, b/c I couldn't
    reproduce it at home, only at work. Perhaps, error I'll post it
    tomorrow.

    I want to see if anyone can see the issue here or suggest an
    alternative design.

    Thanks

  • newbarker@gmail.com

    #2
    Re: using two strings values as a key to the map

    On 22 Sep, 04:01, puzzlecracker <ironsel2...@gm ail.comwrote:
    I need to be able to map two string to some value in the map. I
    consider two alternatives to implement : using pair class or using a
    separate class/struct containing two member strings. I prefer the
    latter for it's more descriptive. However, in the latter
    implementation (equivalent of which  is shown below), I got some
    compiler errors on gcc 3.3.1 with MyClass.
    >
    #include<map>
    #include <string>
    >
    using namespace std;
    >
    struct MyClass
    {
         MyClass ( const string &a, const  string  & b):a_(a),b_(b){ }
         string a_;
         string b_;
    >
    };
    >
    inline bool operator <(const MyClass &a, const MyClass & b)
    {
         return a.a_<b.a_ ||(a.a_==b.a_?a .b_<b.b_:false) ;}
    >
    int main()
    {
       //This caused the error
        map<MyClass, MyClass *>m;
        MyClass my("Foo", "Bar");
        m.find(my);
    >
    //This fixed it
        map<MyClass, MyClass *>m1;
        m1.find(MyClass ("Foo","Bar" ));
    >
    }
    >
    Unfortunately, I can't show the compiler error, b/c  I couldn't
    reproduce it at home, only at work. Perhaps,  error I'll post it
    tomorrow.
    >
    I want to see  if anyone can see the issue here or suggest an
    alternative  design.
    >
    Thanks
    That compiled ok here using Microsoft Visual C++ 2003 (7.1). I would
    use a std::pair myself. Less to write and I think it's MORE
    descriptive and people know exactly how a std::pair works but need to
    look at the home-grown entity including the operator< implementation
    before they're comfortable with it.

    Regards,

    Pete

    Comment

    • Barry

      #3
      Re: using two strings values as a key to the map

      On 9ÔÂ22ÈÕ, ÉÏÎç11ʱ01·Ö, puzzlecracker <ironsel2....@g mail.comwrote:
      I need to be able to map two string to some value in the map. I
      consider two alternatives to implement : using pair class or using a
      separate class/struct containing two member strings. I prefer the
      latter for it's more descriptive. However, in the latter
      implementation (equivalent of which is shown below), I got some
      compiler errors on gcc 3.3.1 with MyClass.
      >
      #include<map>
      #include <string>
      >
      using namespace std;
      >
      struct MyClass
      {
      MyClass ( const string &a, const string & b):a_(a),b_(b){ }
      string a_;
      string b_;
      >
      };
      >
      inline bool operator <(const MyClass &a, const MyClass & b)
      {
      return a.a_<b.a_ ||(a.a_==b.a_?a .b_<b.b_:false) ;}
      >
      int main()
      {
      //This caused the error
      map<MyClass, MyClass *>m;
      MyClass my("Foo", "Bar");
      m.find(my);
      >
      //This fixed it
      map<MyClass, MyClass *>m1;
      m1.find(MyClass ("Foo","Bar" ));
      >
      }
      >
      Unfortunately, I can't show the compiler error, b/c I couldn't
      reproduce it at home, only at work. Perhaps, error I'll post it
      tomorrow.
      >
      I want to see if anyone can see the issue here or suggest an
      alternative design.
      >

      The standard containers require the types to be Assignable.
      In your code, MyClass is not,
      if the compiler have concept checking, compile error would be
      produced.

      HTH.

      --
      Best Regards
      Barry

      Comment

      • anon

        #4
        Re: using two strings values as a key to the map

        Barry wrote:
        On 9ÔÂ22ÈÕ, ÉÏÎç11ʱ01·Ö, puzzlecracker <ironsel2...@gm ail.comwrote:
        >I need to be able to map two string to some value in the map. I
        >consider two alternatives to implement : using pair class or using a
        >separate class/struct containing two member strings. I prefer the
        >latter for it's more descriptive. However, in the latter
        >implementati on (equivalent of which is shown below), I got some
        >compiler errors on gcc 3.3.1 with MyClass.
        Your compiler is too old. I have no problems using g++ 4.1.3
        >>
        >#include<map >
        >#include <string>
        >>
        >using namespace std;
        >>
        >struct MyClass
        >{
        > MyClass ( const string &a, const string & b):a_(a),b_(b){ }
        > string a_;
        > string b_;
        >>
        >};
        >>
        >inline bool operator <(const MyClass &a, const MyClass & b)
        >{
        > return a.a_<b.a_ ||(a.a_==b.a_?a .b_<b.b_:false) ;}
        >>
        >int main()
        >{
        > //This caused the error
        > map<MyClass, MyClass *>m;
        > MyClass my("Foo", "Bar");
        > m.find(my);
        >>
        >//This fixed it
        > map<MyClass, MyClass *>m1;
        > m1.find(MyClass ("Foo","Bar" ));
        >>
        >}
        >>
        >Unfortunatel y, I can't show the compiler error, b/c I couldn't
        >reproduce it at home, only at work. Perhaps, error I'll post it
        >tomorrow.
        >>
        >I want to see if anyone can see the issue here or suggest an
        >alternative design.
        >>
        >
        >
        The standard containers require the types to be Assignable.
        In your code, MyClass is not,
        if the compiler have concept checking, compile error would be
        produced.
        This compiles using g++ 4.1.3

        int main()
        {
        MyClass a("Foo1", "Bar1");
        MyClass b("Foo2", "Bar2");

        b = a;

        std::cout<<b.a_ <<std::endl;
        std::cout<<b.b_ <<std::endl;
        }

        (off course, include iostream)

        Am I causing undefined behavior somehow?

        Comment

        • puzzlecracker

          #5
          Re: using two strings values as a key to the map

          On Sep 22, 5:37 am, Barry <dhb2...@gmail. comwrote:
          On 9ÔÂ22ÈÕ, ÉÏÎç11ʱ01·Ö, puzzlecracker <ironsel2....@g mail.comwrote:
          >
          >
          >
          I need to be able to map two string to some value in the map. I
          consider two alternatives to implement : using pair class or using a
          separate class/struct containing two member strings. I prefer the
          latter for it's more descriptive. However, in the latter
          implementation (equivalent of which is shown below), I got some
          compiler errors on gcc 3.3.1 with MyClass.
          >
          #include<map>
          #include <string>
          >
          using namespace std;
          >
          struct MyClass
          {
          MyClass ( const string &a, const string & b):a_(a),b_(b){ }
          string a_;
          string b_;
          >
          };
          >
          inline bool operator <(const MyClass &a, const MyClass & b)
          {
          return a.a_<b.a_ ||(a.a_==b.a_?a .b_<b.b_:false) ;}
          >
          int main()
          {
          //This caused the error
          map<MyClass, MyClass *>m;
          MyClass my("Foo", "Bar");
          m.find(my);
          >
          //This fixed it
          map<MyClass, MyClass *>m1;
          m1.find(MyClass ("Foo","Bar" ));
          >
          }
          >
          Unfortunately, I can't show the compiler error, b/c I couldn't
          reproduce it at home, only at work. Perhaps, error I'll post it
          tomorrow.
          >
          I want to see if anyone can see the issue here or suggest an
          alternative design.
          >
          The standard containers require the types to be Assignable.
          In your code, MyClass is not,
          if the compiler have concept checking, compile error would be
          produced.
          >
          HTH.
          >
          --
          Best Regards
          Barry
          Assignable?

          Do I need a copy constructor and operator =?


          How would it be implemented with pair?

          Thanks

          Comment

          • Juha Nieminen

            #6
            Re: using two strings values as a key to the map

            Barry wrote:
            >struct MyClass
            >{
            > MyClass ( const string &a, const string & b):a_(a),b_(b){ }
            > string a_;
            > string b_;
            >>
            >};
            >
            The standard containers require the types to be Assignable.
            In your code, MyClass is not,
            Exactly how is it not assignable?

            Comment

            • Thomas J. Gritzan

              #7
              Re: using two strings values as a key to the map

              puzzlecracker wrote:
              >>struct MyClass
              >>{
              >> MyClass ( const string &a, const string & b):a_(a),b_(b){ }
              >> string a_;
              >> string b_;
              >>};
              >>inline bool operator <(const MyClass &a, const MyClass & b)
              >>{
              >> return a.a_<b.a_ ||(a.a_==b.a_?a .b_<b.b_:false) ;}
              Assignable?
              >
              Do I need a copy constructor and operator =?
              No, Barry is wrong. Your struct is copy constructable and assignable.

              The compiler automatically defines a copy constructor and a copy
              assignment operator for you. These work element-wise, that is, if all
              elements of the struct are copy constructable and assignable, the struct
              is, too.
              How would it be implemented with pair?
              Just replace MyClass with std::pair<std:: string,std::str ing>.
              std::pair already has a correct operator< implemented.

              You can then initialize a std::pair with the make_pair helper function:

              m1.find( std::make_pair( "Foo","Bar" ) );

              --
              Thomas

              Comment

              • puzzlecracker

                #8
                Re: using two strings values as a key to the map

                On Sep 22, 9:13 am, "Thomas J. Gritzan" <phygon_antis.. .@gmx.de>
                wrote:
                puzzlecracker wrote:
                >struct MyClass
                >{
                >     MyClass ( const string &a, const  string  & b):a_(a),b_(b){ }
                >     string a_;
                >     string b_;
                >};
                >inline bool operator <(const MyClass &a, const MyClass & b)
                >{
                >     return a.a_<b.a_ ||(a.a_==b.a_?a .b_<b.b_:false) ;}
                Assignable?
                >
                Do I need a copy constructor and operator =?
                >
                No, Barry is wrong. Your struct is copy constructable and assignable.
                >
                The compiler automatically defines a copy constructor and a copy
                assignment operator for you. These work element-wise, that is, if all
                elements of the struct are copy constructable and assignable, the struct
                is, too.
                >
                How would it be implemented with pair?
                >
                Just replace MyClass with std::pair<std:: string,std::str ing>.
                std::pair already has a correct operator< implemented.
                >
                You can then initialize a std::pair with the make_pair helper function:
                >
                m1.find( std::make_pair( "Foo","Bar" ) );
                >
                --
                Thomas
                how is operator< implemented if I have two strings not just one. I
                think, i still need to supply the functor or operator <.

                Comment

                • James Kanze

                  #9
                  Re: using two strings values as a key to the map

                  On Sep 22, 11:37 am, Barry <dhb2...@gmail. comwrote:
                  On 9?22?, ??11?01?, puzzlecracker <ironsel2...@gm ail.comwrote:
                  I need to be able to map two string to some value in the
                  map. I consider two alternatives to implement : using pair
                  class or using a separate class/struct containing two member
                  strings. I prefer the latter for it's more descriptive.
                  However, in the latter implementation (equivalent of which
                  is shown below), I got some compiler errors on gcc 3.3.1
                  with MyClass.
                  #include<map>
                  #include <string>
                  using namespace std;
                  struct MyClass
                  {
                  MyClass ( const string &a, const string & b):a_(a),b_(b){ }
                  string a_;
                  string b_;
                  };
                  inline bool operator <(const MyClass &a, const MyClass & b)
                  {
                  return a.a_<b.a_ ||(a.a_==b.a_?a .b_<b.b_:false) ;}
                  int main()
                  {
                  //This caused the error
                  map<MyClass, MyClass *>m;
                  MyClass my("Foo", "Bar");
                  m.find(my);
                  //This fixed it
                  map<MyClass, MyClass *>m1;
                  m1.find(MyClass ("Foo","Bar" ));
                  }
                  >
                  Unfortunately, I can't show the compiler error, b/c I
                  couldn't reproduce it at home, only at work. Perhaps, error
                  I'll post it tomorrow.
                  I want to see if anyone can see the issue here or suggest
                  an alternative design.
                  The standard containers require the types to be Assignable.
                  In your code, MyClass is not,
                  It looks Assignable to me. What makes you say that it isn't
                  Assignable?
                  if the compiler have concept checking, compile error would be
                  produced.
                  I have no problem compiling it with g++ (4.1.0), with all
                  checking turned on.

                  --
                  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

                  • James Kanze

                    #10
                    Re: using two strings values as a key to the map

                    On Sep 22, 3:13 pm, "Thomas J. Gritzan" <phygon_antis.. .@gmx.de>
                    wrote:
                    puzzlecracker wrote:
                    >struct MyClass
                    >{
                    > MyClass ( const string &a, const string & b):a_(a),b_(b){ }
                    > string a_;
                    > string b_;
                    >};
                    >inline bool operator <(const MyClass &a, const MyClass & b)
                    >{
                    > return a.a_<b.a_ ||(a.a_==b.a_?a .b_<b.b_:false) ;}
                    Assignable?
                    Do I need a copy constructor and operator =?
                    No, Barry is wrong. Your struct is copy constructable and
                    assignable.
                    The compiler automatically defines a copy constructor and a
                    copy assignment operator for you. These work element-wise,
                    that is, if all elements of the struct are copy constructable
                    and assignable, the struct is, too.
                    How would it be implemented with pair?
                    Just replace MyClass with std::pair<std:: string,std::str ing>.
                    std::pair already has a correct operator< implemented.
                    You can then initialize a std::pair with the make_pair helper function:
                    m1.find( std::make_pair( "Foo","Bar" ) );
                    But why doesn't his operator< work? It looks OK to me (although
                    I've have written the expression:

                    return a.a_ < b.a_ || (a.a_ == b.a_ && a.b_ < b.b_) ;

                    ..)

                    For once someone is doing the right thing, and trying to write
                    readable code (rather than using std::pair). Let's not
                    discourage him.

                    --
                    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

                    • Thomas J. Gritzan

                      #11
                      Re: using two strings values as a key to the map

                      James Kanze wrote:
                      On Sep 22, 3:13 pm, "Thomas J. Gritzan" <phygon_antis.. .@gmx.de>
                      wrote:
                      >puzzlecracke r wrote:
                      >>How would it be implemented with pair?
                      >
                      >Just replace MyClass with std::pair<std:: string,std::str ing>.
                      >std::pair already has a correct operator< implemented.
                      >
                      >You can then initialize a std::pair with the make_pair helper function:
                      >
                      >m1.find( std::make_pair( "Foo","Bar" ) );
                      >
                      But why doesn't his operator< work? It looks OK to me (although
                      I've have written the expression:
                      It looks ok to me, too, and Comeau accepts it. It might not be the
                      original copy'n'pasted code.
                      return a.a_ < b.a_ || (a.a_ == b.a_ && a.b_ < b.b_) ;
                      >
                      .)
                      >
                      For once someone is doing the right thing, and trying to write
                      readable code (rather than using std::pair). Let's not
                      discourage him.
                      Heh, he asked for std::pair, don't blame me! :-)

                      In a hobby project I had a
                      std::map< std::pair<int, std::pair<int,i nt, valueType >,
                      and it was really ugly.

                      In the long term, using a struct with a good name (or at least a typedef
                      for std::pair) is the better idea.

                      --
                      Thomas

                      Comment

                      Working...