Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Re: std::map reports: Invalid < operator

Reply
Thread Tools

Re: std::map reports: Invalid < operator

 
 
joecook@gmail.com
Guest
Posts: n/a
 
      01-11-2009
On Jan 10, 11:17*pm, "(2b|!2b)==?" <(E-Mail Removed)> wrote:
> I have a struct defined like this:
>
> struct MyStruct
> {
> public:
> * * * * MyStruct(const std::string& s, unsigned char i): m_s(s), m_i(i)
> * * * * {}
>
> * * * * MyStruct(const MyStruct& ms){/*....*/}
> * * * * MyStruct& operator=(const MyStruct& ms){ /* .... */}
> * * * * ~MyStruct(){}
>
> * * * * bool operator< (const MyStruct& ms) const
> * * * * {
> * * * * * * * * if (m_i < ms.m_i)
> * * * * * * * * * * * * return true;
> * * * * * * * * else
> * * * * * * * * * * * * return m_s < ms.m_s ;
> * * * * }
>
> private:
> * * * * std::string m_s;
> * * * * unsigned char m_i ;
>
> };
>
> When I use this struct as a key in a std::map, I am getting a runtime
> error: "Invalid '<' operator - what is wrong with the code above?.
> Incidentally, I appear to be coming unstuck with this sorting predicates
> - are there any good online references anyone can recommend?


Runtime error? Sneaky. MyStruct can only be used as a key type, not a
value type (since it isn't Default Constructable for one), but you
aren't doing that..

so..the answer I bet is this:
Let's say you have two elements pushed back:

1. "b,4",
2. "a,5"

Is 1. < 2. (returns 'true', because 4 is less than 5)
Is 2. < 1. (goes into "else" branch, and returns 'true' because 'a' is
less than 'b'/

The fact that 1 is less than 2, and 2 is less than 1, means there is
no strict weak ordering. The fact that your compiler did something to
check this at run-time is impressive.

Joe Cook
 
Reply With Quote
 
 
 
 
joecook@gmail.com
Guest
Posts: n/a
 
      01-11-2009
On Jan 11, 1:00*am, (E-Mail Removed) wrote:
> On Jan 10, 11:17*pm, "(2b|!2b)==?" <(E-Mail Removed)> wrote:

<snip>
> > * * * * bool operator< (const MyStruct& ms) const
> > * * * * {
> > * * * * * * * * if (m_i < ms.m_i)
> > * * * * * * * * * * * * return true;
> > * * * * * * * * else
> > * * * * * * * * * * * * return m_s < ms.m_s ;
> > * * * * }

<snip>

One way to change this so it would be correct would be:

bool operator< (const MyStruct& ms) const
{
if (m_i < ms.m_i)
return true;
else if(m_i == ms.m.i)
return m_s < ms.m_s ;
return false;
}
 
Reply With Quote
 
 
 
 
James Kanze
Guest
Posts: n/a
 
      01-11-2009
On Jan 11, 7:00 am, (E-Mail Removed) wrote:
> On Jan 10, 11:17 pm, "(2b|!2b)==?" <(E-Mail Removed)> wrote:
> > I have a struct defined like this:


> > When I use this struct as a key in a std::map, I am getting
> > a runtime error: "Invalid '<' operator - what is wrong with
> > the code above?. Incidentally, I appear to be coming
> > unstuck with this sorting predicates - are there any good
> > online references anyone can recommend?


> Runtime error? Sneaky. MyStruct can only be used as a key
> type, not a value type (since it isn't Default Constructable
> for one), but you aren't doing that..


There's no requirement that value types be default
constructable. In fact, the standard doesn't even have a
constraint DefaultConstructable.

> so..the answer I bet is this: Let's say you have two elements
> pushed back:


> 1. "b,4",
> 2. "a,5"


> Is 1. < 2. (returns 'true', because 4 is less than 5)
> Is 2. < 1. (goes into "else" branch, and returns 'true' because 'a' is
> less than 'b'/


> The fact that 1 is less than 2, and 2 is less than 1, means
> there is no strict weak ordering. The fact that your compiler
> did something to check this at run-time is impressive.


Yes and no. It would be really impressive if the compiler
failed to compile the code. But detecting that the error is due
to an illegal ordering relationship (rather than just ending up
with a bounds check error or whatever) is pretty good.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
joecook@gmail.com
Guest
Posts: n/a
 
      01-11-2009
On Jan 11, 5:54*am, James Kanze <(E-Mail Removed)> wrote:
>
> Yes and no. *It would be really impressive if the compiler
> failed to compile the code. *But detecting that the error is due
> to an illegal ordering relationship (rather than just ending up
> with a bounds check error or whatever) is pretty good.


Agreed. Either would be a good gcc addition however. I can't get gcc
to fail in a similar manner.

Joe
 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      01-11-2009
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> On Jan 11, 5:54*am, James Kanze <(E-Mail Removed)> wrote:
>>
>> Yes and no. *It would be really impressive if the compiler
>> failed to compile the code. *But detecting that the error is due
>> to an illegal ordering relationship (rather than just ending up
>> with a bounds check error or whatever) is pretty good.

>
> Agreed. Either would be a good gcc addition however. I can't get gcc
> to fail in a similar manner.


What comes to mind is the following test: let comp() be a binary
predicate, then

bool error_comp ( Type const & lhs, Type const & rhs ) {
bool le = comp( lhs, rhs );
bool gr = comp( rhs, lhs );
if ( le && gr ) {
throw some error;
}
return ( le );
}

performs a simple check. I don't think that checking for transitivity is
feasible in a search tree since the assumption of transitivity is built
into the data structure (tests whose outcome can be inferred by
transitivity are avoided). Also, it is not an error when le = gr = false,
since that just flags equivalence. However, because equivalence of keys is
defined as such, sometimes both tests have to performed anyway. I
conjecture that it is precisely in these situations where the STL of the OP
flags the error.

I shall note that the comparison predicate of the OP fails the above check
for

lhs = ( "z", 0x11 )
rhs = ( "a", 0x99 )


Best

Kai-Uwe Bux
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      01-11-2009
On Jan 11, 4:03 pm, (E-Mail Removed) wrote:
> On Jan 11, 5:54 am, James Kanze <(E-Mail Removed)> wrote:
> > Yes and no. It would be really impressive if the compiler
> > failed to compile the code. But detecting that the error is
> > due to an illegal ordering relationship (rather than just
> > ending up with a bounds check error or whatever) is pretty
> > good.


> Agreed. Either would be a good gcc addition however. I can't
> get gcc to fail in a similar manner.


Getting it to systematically fail, on instantiation, is probably
not feasable. It should be possible to add a few pragmatic
checks which do cause it to fail once you start adding elements
to the container, most of the time when there might be an
ambiguity.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
Triple-DES
Guest
Posts: n/a
 
      01-12-2009
On 11 Jan, 11:54, James Kanze <(E-Mail Removed)> wrote:
> On Jan 11, 7:00 am, (E-Mail Removed) wrote:
> > Runtime error? *Sneaky. MyStruct can only be used as a key
> > type, not a value type (since it isn't Default Constructable
> > for one), but you aren't doing that..

>
> There's no requirement that value types be default
> constructable. *In fact, the standard doesn't even have a
> constraint DefaultConstructable.
>


I suppose he meant mapped_type, since value_type is pair<const Key, T>
for map<Key,T>. The description of operator[] implies that mapped_type
must be default constructible.
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      01-12-2009
On Jan 12, 8:30 am, Triple-DES <(E-Mail Removed)> wrote:
> On 11 Jan, 11:54, James Kanze <(E-Mail Removed)> wrote:


> > On Jan 11, 7:00 am, (E-Mail Removed) wrote:
> > > Runtime error? Sneaky. MyStruct can only be used as a key
> > > type, not a value type (since it isn't Default
> > > Constructable for one), but you aren't doing that..


> > There's no requirement that value types be default
> > constructable. In fact, the standard doesn't even have a
> > constraint DefaultConstructable.


> I suppose he meant mapped_type, since value_type is pair<const
> Key, T> for map<Key,T>. The description of operator[] implies
> that mapped_type must be default constructible.


Only if you use operator[].

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
invalid character in base-64 string and invalid postback or callba kevin ASP .Net 0 01-16-2008 09:39 PM
How do fix: "Wrong number of arguments" / "invalid propert assignment"/ "Invalid argument" Java Guy Javascript 1 10-15-2006 08:41 PM
How do fix: "Wrong number of arguments" / "invalid propert assignment"/ "Invalid argument" Java Guy Java 1 10-15-2006 08:31 PM
Invalid URI: There is an invalid sequence in the string. Error!! Patrick.O.Ige ASP .Net 1 07-02-2006 11:21 AM
invalid@invalid.org Hank Sniadoch Computer Information 1 08-20-2004 11:24 AM



Advertisments