оператор stringstream>> завершается с ошибкой как функция, но работает как экземпляр?
-
10-07-2019 - |
Вопрос
Я пишу простой код, который извлечет кучу пар name, int из файла.Я модифицирую существующий код, который просто использует:
string chrom;
unsigned int size;
while ( cin >> chrom >> size ) {
// save values
}
Но я хочу использовать другой (аналогичный) входной файл, который содержит те же первые два столбца, но за которым следуют другие данные (которые будут проигнорированы).Поэтому я пишу:
string chrom;
unsigned int size;
string line;
while ( getline(cin, line) ) {
if( stringstream(line) >> chrom >> size ) {
// save values
}
}
Но это не удается скомпилировать, выдавая типичный непристойный шаблон std lib, извергающий:
error: no match for "operator>>" in "std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >(((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >*)(& line))), std::operator|(_S_out, _S_in)) >> chrom"
istream:131: note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>& (*)(std::basic_istream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
[...another dozen lines...]
Правильно.строка - это не std::string , а некоторая вариация std::basic_string и т.д.Однако работает явное создание экземпляра stringstream.
string chrom;
unsigned int size;
string line;
while ( getline(genome, line) ) {
stringstream ss(line);
if ( ss >> chrom >> size ) {
// save values
}
// Discard remainder of line
}
Почему?Что не так с первым случаем?В пример basic_io в разделе всегда полезно cplusplus.com работает, почему не работает мой код?
Обновить:Еще одна точка отсчета:временный stringstream работает, когда первое извлеченное значение является int вместо string:
unsigned int chrom; // works as int...
unsigned int size;
string line;
while ( getline(cin, line) ) {
if( stringstream(line) >> chrom >> size ) {
// save values
}
}
Решение
Три группы функций-членов и одна группа глобальных функций перегружают этот "оператор извлечения" (>>), см. http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/.
- stringstream(строка);--создан временный объект
- stringstream ss(строка);-- обычный объект.
когда "chrom" имеет значение int, operator >> перегружается как арифметический экстрактор, который является функциями-членами.Как обычный объект, так и временный объект работают нормально.
Когда "chrom" является строкой, оператор >> должен быть перегружен как istream& operator>> (istream& is, char* str)
, это глобальная функция, которая должна принимать ссылку на объект в качестве параметра.Однако, учитывая временный объект, нам не разрешается передавать временные объекты по неконстантной ссылке в стандартном C ++.Функция перегрузки не может получить ссылку на временный объект, если функция перегрузки не определена как istream& operator>> (const istream& is, char* str)
.К сожалению, это не факт.Функция (ы) не может быть перегружена в случае временного объекта и, следовательно, выдает ошибку типа error: no match for function...
Другие советы
Чтобы расширить ответ Джона Уэлдона, оператор extrace ">>" выполняет две вещи:
- Извлекает следующее значение и помещает его в переменную справа от оператора.
- Увеличивает текущее положение потока слева.
Следовательно, он изменяет как свой левый, так и правый операнд.В вашем случае левый операнд является временным значением, и компилятор не одобряет его изменение.
Некоторые операторы в C и C ++ требуют, чтобы значение слева от оператора было значением lvalue, т. е.что они могут быть изменены.
Здесь это более полное объяснение.
Потому что первое значение, извлеченное из stringstream, является std::string .Если бы это был, скажем, int, версия stringstream (строка) работала бы.
В stringstream для std::string нет оператора функции-члена>>.Следовательно, временный поток не может функционировать как значение lvalue.
Не то чтобы я полностью понимал вышесказанное...но, возможно, это отправная точка для лучшего ответа.