By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,301 Members | 1,752 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,301 IT Pros & Developers. It's quick & easy.

using two strings values as a key to the map

P: n/a
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

Sep 22 '08 #1
Share this Question
Share on Google+
10 Replies


P: n/a
On 22 Sep, 04:01, puzzlecracker <ironsel2...@gmail.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
Sep 22 '08 #2

P: n/a
On 9月22日, 上午11时01分, puzzlecracker <ironsel2....@gmail.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
Sep 22 '08 #3

P: n/a
Barry wrote:
On 9月22日, 上午11时01分, puzzlecracker <ironsel2...@gmail.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.
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"));

}

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.
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?
Sep 22 '08 #4

P: n/a
On Sep 22, 5:37 am, Barry <dhb2...@gmail.comwrote:
On 9月22日, 上午11时01分, puzzlecracker <ironsel2....@gmail.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
Sep 22 '08 #5

P: n/a
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?
Sep 22 '08 #6

P: n/a
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::string>.
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
Sep 22 '08 #7

P: n/a
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::string>.
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 <.

Sep 22 '08 #8

P: n/a
On Sep 22, 11:37 am, Barry <dhb2...@gmail.comwrote:
On 9?22?, ??11?01?, puzzlecracker <ironsel2...@gmail.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:ja*********@gmail.com
Conseils en informatique orient閑 objet/
Beratung in objektorientierter Datenverarbeitung
9 place S閙ard, 78210 St.-Cyr-l'蒫ole, France, +33 (0)1 30 23 00 34
Sep 22 '08 #9

P: n/a
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::string>.
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:ja*********@gmail.com
Conseils en informatique orient閑 objet/
Beratung in objektorientierter Datenverarbeitung
9 place S閙ard, 78210 St.-Cyr-l'蒫ole, France, +33 (0)1 30 23 00 34
Sep 22 '08 #10

P: n/a
James Kanze wrote:
On Sep 22, 3:13 pm, "Thomas J. Gritzan" <phygon_antis...@gmx.de>
wrote:
>puzzlecracker wrote:
>>How would it be implemented with pair?
>Just replace MyClass with std::pair<std::string,std::string>.
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,int, 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
Sep 22 '08 #11

This discussion thread is closed

Replies have been disabled for this discussion.