Я работаю над устаревшим кодом со старым компилятором Solaris на Solaris 10 (здесь нет нового C ++ 0x ;-)

-bash-3.2 $ CC -V

Копия: Sun C ++ 5.12 SunOS_sparc 2011/11/16

У меня есть сторонний класс словаря с итератором

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()();
    ...
};

Мой код должен пройти через каждый элемент в словаре, но имеет ошибку компиляции, которую я не могу объяснить:

DictIterator iterator(theDictionary);
while(iterator())
{
    cout << iterator.key(); 
}

Не работает с "filename.cc", line 42: Error: The operation "ostream_withassign<<Key" is illegal.

Но эта версия работает:

DictIterator iterator(theDictionary);
while(iterator())
{
    Key key(iterator.key());
    cout << key; 
}

Очевидно, у меня есть обходной путь, но я подумал, что, поскольку DictIterator.key() возвращает K (не ссылку), эти два фрагмента очень похожи. Может ли кто-нибудь сообщить мне, в какой странный уголок C ++ я только что наткнулся?

Изменить: для ответа на комментарии << переопределяется ostream& operator(ostream &, Key&);

1
John3136 25 Май 2018 в 09:15

1 ответ

Лучший ответ

operator<< принимает свой правый аргумент по неконстантной ссылке на lvalue. Это означает, что временные объекты не могут быть привязаны к этому аргументу.

Метод key() возвращает временный. Только создав локальную переменную, вы можете превратить эту временную переменную в переменную, к которой может быть привязана ссылка lvalue.

Изменение аргумента оператора на const Key& решает эту проблему, поскольку ссылка на const lvalue может связываться с временными объектами. Это должно быть минимально инвазивное и безопасное изменение - оно могло не работать, только если оператор вывода использовал неконстантную функциональность записываемого объекта, что само по себе было бы большим красным флажком. Однако, если существующий код не является корректным по константе (т.е. функции-члены, которые не изменяют свои объекты, не всегда помечаются как const), это может привести к долгому концу исправления таких нарушений корректности с константой.

3
Sebastian Redl 28 Май 2018 в 08:01