Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 1

Qt-interest Archive, May 2008
QMap: no match for ‘operator<’ found (although it's defined)


Message 1 in thread

Dear list,
I have defined a class and want to use it as a key type with a QMap. I
overloaded the < operator but the compiler can't find it.  The class is
called TranslationDirection, it's defined in a namespace called LLCommon
and the compiler error is:

/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qmap.h: In function ‘bool
qMapLessThanKey(const Key&, const Key&) [with Key =
LLCommon::TranslationDirection]’:
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qmap.h:667:   instantiated
from ‘typename QMap<Key, T>::iterator QMap<Key, T>::erase(QMap<Key,
T>::iterator) [with Key = LLCommon::TranslationDirection, T = QAction*]’
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qmap.h:1015:   instantiated
from ‘void QMutableMapIterator<Key, T>::remove() [with Key =
LLCommon::TranslationDirection, T = QAction*]’
LLCommon/TranslationDirectionManager.cpp:59:   instantiated from here
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qmap.h:104: error: no match
for ‘operator<’ in ‘key1 < key2’
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qchar.h:361: note:
candidates are: bool operator<(QChar, QChar)
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qbytearray.h:470: note:
              bool operator<(const QByteArray&, const QByteArray&)
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qbytearray.h:472: note:
              bool operator<(const QByteArray&, const char*)
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qbytearray.h:474: note:
              bool operator<(const char*, const QByteArray&)
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qstring.h:870: note:
           bool operator<(const char*, const QString&)
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qstring.h:883: note:
           bool operator<(const char*, const QLatin1String&)
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qstring.h:896: note:
           bool operator<(const QLatin1String&, const QLatin1String&)
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qstring.h:1106: note:
            bool operator<(const QStringRef&, const QStringRef&)
LLCommon/TranslationDirection.h:28: note:                 bool
operator<(LLCommon::TranslationDirection&, LLCommon::TranslationDirection&)
make[1]: Leaving directory `/home/daniel/eclipse-lexilector/Lexilector-Qt'
make[1]: *** [release/TranslationDirectionManager.o] Error 1
make: *** [release] Error 2

My understanding is that the compiler recognizes
LLCommon::TranslationDirection as the key type to use with QMap, that it
finds the definition of the overloaded operator but cannot match it.
Please, why is that?

Thanks
Daniel
---
PS:
The class' header file is:

#ifndef TRANSLATIONDIRECTION_H_
#define TRANSLATIONDIRECTION_H_

#include <QString>

namespace LLCommon
{

class TranslationDirection
{
public:
	TranslationDirection(QString &, QString &);
	~TranslationDirection();
	
	bool operator==(TranslationDirection &) const;
	QString & GetSourceLanguage();
	QString & GetTargetLanguage();

	QString & GetText();
	
private:
	QString _source;
	QString _target;
};

} // LLCommon

bool operator<(LLCommon::TranslationDirection & one,
LLCommon::TranslationDirection & other)
{
	return one.GetText() < other.GetText();
}

#endif /*TRANSLATIONDIRECTION_H_*/

--
 [ signature omitted ] 

Message 2 in thread

Daniel Storbeck wrote:
> bool operator<(LLCommon::TranslationDirection & one,
> LLCommon::TranslationDirection & other)

I think you need to implement operator< as a member function of 
LLCommon::TranslationnDirection rather than a global function. Am I right?

--Dave

--
 [ signature omitted ] 

Message 3 in thread

Dave Smith wrote:
> Daniel Storbeck wrote:
>> bool operator<(LLCommon::TranslationDirection & one,
>> LLCommon::TranslationDirection & other)
> 
> I think you need to implement operator< as a member function of 
> LLCommon::TranslationnDirection rather than a global function. Am I right?
> 
> --Dave
Hi Dave,
that gives me the same compiler error:

/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qmap.h:104: error: no match 
for ‘operator<’ in ‘key1 < key2’
LLCommon/TranslationDirection.h:18: note: candidates are: bool 
LLCommon::TranslationDirection::operator<(LLCommon::TranslationDirection&)

---

The header is:

#ifndef TRANSLATIONDIRECTION_H_
#define TRANSLATIONDIRECTION_H_

#include <QString>

namespace LLCommon
{

class TranslationDirection
{
public:
	TranslationDirection(QString &, QString &);
	~TranslationDirection();
	
	// This one works.
	bool operator==(TranslationDirection &) const;
	
	bool operator<(TranslationDirection &);
		
	QString & GetSourceLanguage();
	QString & GetTargetLanguage();

	QString & GetText();
	
private:
	QString _source;
	QString _target;
};

} // LLCommon

/*
// global function
bool operator<(LLCommon::TranslationDirection & one, 
LLCommon::TranslationDirection & other)
{
	return one.GetText() < other.GetText();
}
*/

#endif /*TRANSLATIONDIRECTION_H_*/

---

And the implementation:

#include "TranslationDirection.h"

namespace LLCommon
{

TranslationDirection::TranslationDirection(QString & source, QString & 
target)
	: _source(source), _target(target)
{
}

TranslationDirection::~TranslationDirection()
{
}

bool TranslationDirection::operator==(TranslationDirection & other) const
{
	if ((_source == other.GetSourceLanguage())
			&& (_target == other.GetTargetLanguage()))
		return true;
	else return false;
}

bool TranslationDirection::operator<(TranslationDirection & other)
{
	return GetText() < other.GetText();
}

QString & TranslationDirection::GetSourceLanguage()
{
	return _source;
}

QString & TranslationDirection::GetTargetLanguage()
{
	return _target;
}

QString & TranslationDirection::GetText()
{
	return QString((_source + " > " + _target));
}

}

---

I'll also try with two arguments.
Thank you
Daniel

--
 [ signature omitted ] 

Message 4 in thread

You need to be const correct. For a member function use:

bool 
TranslationDirection::operator<(TranslationDirection const & other) const

for a global function use:

bool operator<(TranslationDirection const & lhs,
               TranslationDirection const & rhs)


GetText() should then also be const correct:

QString const & GetText() const;


Note that you can have both versions:

QString & GetText();
QString const & GetText() const;

But your current GetText returns a reference to a local variable. Your
compiler should warn against this. With gcc maybe you need -W -Wall.

QString & TranslationDirection::GetText()
{
        return QString((_source + " > " + _target));
}

A more correct version would be: 

QString TranslationDirection::GetText() const
{
        return _source + " > " + _target;
}

--
 [ signature omitted ] 

Message 5 in thread

Christoph Bartoschek wrote:
> You need to be const correct. For a member function use:
> 
> bool 
> TranslationDirection::operator<(TranslationDirection const & other) const
> 
> for a global function use:
> 
> bool operator<(TranslationDirection const & lhs,
>                TranslationDirection const & rhs)
> 
It works! Thank you so much, Christoph. I actually used const in front 
of the type name and behind the signature but not behind the typename. 
Maybe I was mislead by the example code in the QMap Reference. Also the 
compiler error messages always listed candidates with the const keyword 
in front of the type names.
Give me one last hint, please. How could I have figured out myself how 
to be const correct without trying all combinations?
Thanks
Daniel

--
 [ signature omitted ] 

Message 6 in thread

Daniel Storbeck wrote:


> It works! Thank you so much, Christoph. I actually used const in front
> of the type name and behind the signature but not behind the typename.
> Maybe I was mislead by the example code in the QMap Reference. Also the
> compiler error messages always listed candidates with the const keyword
> in front of the type names.
> Give me one last hint, please. How could I have figured out myself how
> to be const correct without trying all combinations?
> Thanks
> Daniel

1.

TranslationDirection const & lhs  

is the same as

const TranslationDirection & lhs

The Trolltech documentation and lots of people prefer the second version. I
prefer the first one because it makes it easy to read the type from right
to left:

"lhs is a reference to a const TranslationDirection"

The correct signature could have also been: 

bool operator<(const TranslationDirection & lhs,
               const TranslationDirection & rhs);


2. How to find the error?  The compiler does not give a very good message:

qmap.h:106: error: no match for âoperator<â in âkey1 < key2â

To find out the cause you need to look into qmap.h what type key1 and key2
have.

In qmap.h you see:

const Key &key1, const Key &key2

The compiler tells you what Key is (LLCommon::TranslationDirection). Then
you know that you need an operator< for two

const LLCommon::TranslationDirection & 

3. One learns really quickly to be const correct wihtout reading the
compiler message. :)

Christoph

--
 [ signature omitted ] 

Message 7 in thread

Christoph Bartoschek wrote:
> TranslationDirection const & lhs  
> 
> is the same as
> 
> const TranslationDirection & lhs

I wasn't fully aware of that. Anyway, the reason why my code didn't work 
when I used the const keywords in front of the type name and behind the 
signature, was the GetText() function that wasn't declared also const. 
So, your hint on setting it const actually solved the problem. Thank you 
again.
Best
Daniel

--
 [ signature omitted ] 

Message 8 in thread

Daniel Storbeck wrote:
>Give me one last hint, please. How could I have figured out myself how
>to be const correct without trying all combinations?

What you needed was this:
bool operator<(Type t1, Type t2)
{ 
    // ....
}

For efficiency purposes, you may want to pass by reference. After all, 
you're just comparing two items, there's no need to create copies of 
them. 

Well, QMap doesn't allow you to modify the elements while it's sorting, 
right? So you needed constant references:

bool operator<(const Type& t1, const Type& t2)
{ 
    // ....
}

Now, if you have a constant object, you can only call const functions on 
it. In general, all accessors are const. And I don't have to tell you 
that, if the modifier applies to the _function_ (as opposed to the return 
type or any arguments) it comes at the end:

     QString GetText() const;

That's it!

Note that the following is syntactically the same:
	const Type &
	Type const &
the following is the same as well:
	const Type *
	Type const *
but the following is not the same as the last two:
	Type * const

-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.


Message 9 in thread

Thiago Macieira wrote:
> Now, if you have a constant object, you can only call const functions on 
> it. In general, all accessors are const. And I don't have to tell you 
> that, if the modifier applies to the _function_ (as opposed to the return 
> type or any arguments) it comes at the end:

Yes, that pretty much explains the whole problem. And, yes, someone had 
to tell me, because I'm new to C++ and Qt, already came across that part 
of the "theory" but I forgot it and was completely lost.
Thank you for reminding me.
Best
Daniel

--
 [ signature omitted ] 

Message 10 in thread

Hi Dave,
trying with two arguments results in the same error message plus:

...
LLCommon/TranslationDirection.h:23: error: ‘bool 
LLCommon::TranslationDirection::operator<(LLCommon::TranslationDirection&, 
LLCommon::TranslationDirection&)’ must take exactly one argument
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qmap.h: In function ‘bool 
qMapLessThanKey(const Key&, const Key&) [with Key = 
LLCommon::TranslationDirection]’:
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qmap.h:667:   instantiated 
from ‘typename QMap<Key, T>::iterator QMap<Key, T>::erase(QMap<Key, 
T>::iterator) [with Key = LLCommon::TranslationDirection, T = QAction*]’
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qmap.h:1015:   instantiated 
from ‘void QMutableMapIterator<Key, T>::remove() [with Key = 
LLCommon::TranslationDirection, T = QAction*]’
LLCommon/TranslationDirectionManager.cpp:59:   instantiated from here
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qmap.h:104: error: no match 
for ‘operator<’ in ‘key1 < key2’
LLCommon/TranslationDirection.h:23: note: candidates are: bool 
LLCommon::TranslationDirection::operator<(LLCommon::TranslationDirection&, 
LLCommon::TranslationDirection&)
/usr/local/Trolltech/Qt-4.3.4/include/QtCore/qchar.h:361: note: 
         bool operator<(QChar, QChar)
...

---

Header file:

...
bool operator<(TranslationDirection &, TranslationDirection &);
...

---

Implementation:

...
bool TranslationDirection::operator<(TranslationDirection & one, 
TranslationDirection & other)
{
	return one.GetText() < other.GetText();
}
...

---

I'm confused...
Thanks
Daniel

--
 [ signature omitted ]