I'm working on some legacy code with an old Solaris compiler on Solaris 10 (no new fangled C++0x here ;-)
-bash-3.2$ CC -V
CC: Sun C++ 5.12 SunOS_sparc 2011/11/16
I've got a 3rd party dictionary class with an iterator
template<K, V>
class DictIterator
{
public:
DictIterator(TheDictClass<K, V>& collection);
K key() const;
V value() const;
// advance the iterator. return true if iterator points to a valid item
bool operator()();
...
};
My code is supposed to go through each item in the dictionary but has a compile error that I can't explain:
DictIterator iterator(theDictionary);
while(iterator())
{
cout << iterator.key();
}
Fails with "filename.cc", line 42: Error: The operation "ostream_withassign<<Key" is illegal.
But this version works:
DictIterator iterator(theDictionary);
while(iterator())
{
Key key(iterator.key());
cout << key;
}
Obviously I've got a workaround but I thought that since DictIterator.key()
returns a K
(not a reference), the two snippets were pretty similar. Can anyone let me know what weird corner of C++ I've just bumped into?
edit: To answer comments, <<
is overridden ostream& operator(ostream &, Key&);
The operator<<
takes its right argument by non-const lvalue reference. This means that temporaries cannot be bound to this argument.
The key()
method returns a temporary. Only by creating a local variable can you turn this temporary into a variable that the lvalue reference can bind to.
Changing the argument of the operator to a const Key&
solves this problem because a const lvalue reference can bind to temporaries. This should be a minimally invasive and safe change - it could only fail to work if the output operator used non-const functionality of the object being written, which would be a big red flag in itself. However, if the existing code is not const-correct (i.e. member functions that do not modify their objects are not consistently marked as const
), this may lead to a long tail of fixing such const-correctness violations.