Извлечь из ifstream без временной переменной?

ifstream предлагает перегрузку operator>> для извлечения значений из следующей строки потока. Тем не менее, я часто ловлю себя на том, что делаю это:

int index;
input >> index;
arr[index] = <something>;

Есть ли способ получить эти данные в [index] без создания этой временной переменной?


person It'sNotALie.    schedule 30.03.2018    source источник
comment
Углубляется на arr и <something>. Но в конечном счете, я склоняюсь к не простому решению.   -  person StoryTeller - Unslander Monica    schedule 30.03.2018
comment
@StoryTeller arr — это просто vector<T>, что-то не связанное с arr и index   -  person It'sNotALie.    schedule 30.03.2018
comment
Даже если вы получите данные в [index] без создания явной локальной (временной) переменной, вы все равно получите безымянную временную переменную. Компилятор может довольно хорошо оптимизировать явную локальную переменную. Я предпочел бы быть явным, чем хитрым, но это только я.   -  person Eljay    schedule 30.03.2018
comment
@Justin, да, наверное, это очень разумный вариант.   -  person It'sNotALie.    schedule 30.03.2018
comment
@Элджей, это правда, я новичок в С++, поэтому я предположил, что там может быть что-то идиоматическое.   -  person It'sNotALie.    schedule 30.03.2018
comment
Говоря об идиоматическом C++. В зависимости от T предварительное построение всего вектора с фиктивными значениями и последующее присвоение может быть само по себе однозначным.   -  person StoryTeller - Unslander Monica    schedule 30.03.2018
comment
@Eljay Однострочная функция будет оптимизирована до тех пор, пока ее реализация видна. Проблема в том, что OP считает более читаемым.   -  person patatahooligan    schedule 30.03.2018
comment
@StoryTeller, можешь немного продолжить? как я уже сказал, все еще немного новичок в С++ :)   -  person It'sNotALie.    schedule 30.03.2018
comment
@Это НЕТАЛИ. - Вы инициализируете T в индексе после его построения. Идет вразрез с c'tors. Это похоже на общедоступный метод init(), отдельный антишаблон. Но это в конечном итоге зависит от T. Я думаю, что в этом вопросе может быть что-то вроде элемента XY.   -  person StoryTeller - Unslander Monica    schedule 30.03.2018
comment
Поскольку обычно ввод может завершиться ошибкой, необходимо убедиться, что попытка чтения была успешной. Интерфейс преднамеренно такой, чтобы сделать тестирование идиоматичным: if (in >> value) { /* use value */ }. Кроме того, порядок оценки не определен, и что-то вроде array[read<int>(in)] = read<T>(in); обязательно сделает неправильную вещь (вашему <something> лучше не читать тот же поток).   -  person Dietmar Kühl    schedule 30.03.2018
comment
Было бы лучше проверить index, это то, что вы думаете, прежде чем использовать его imo   -  person Galik    schedule 30.03.2018
comment
@DietmarKühl В C ++ 17 array[read<int>(in)] = read<T>(in); гарантированно сначала оценивает правую сторону, поэтому у вас будет read<T>(in), затем read<int>(in), затем array[...], затем ... = .... stackoverflow.com/a/38501596/1896169   -  person Justin    schedule 30.03.2018


Ответы (2)


Вы можете написать функцию для извлечения следующего значения из istream:

template <typename T> // T must be DefaultConstructible
T read(std::istream& input) {
    T result;
    input >> result;
    return result;
}

Тогда вы могли бы просто написать:

arr[read<int>(input)] = <something>;

Хотя, наверное, надо написать

arr.at(read<int>(input)) = <something>;

Потому что в противном случае вы подвергаете себя уязвимости переполнения буфера. Если бы во входном файле было целое число за пределами допустимого диапазона, вы бы писали за пределами допустимого диапазона.

person Justin    schedule 30.03.2018
comment
Извините, что означает DefaultConstructible? - person It'sNotALie.; 30.03.2018
comment
@Это НЕТАЛИ. По сути, эта функция позволяет вам написать read<MyType>(input). Эта функция требует, чтобы MyType имел конструктор по умолчанию (конструктор без аргументов), иначе строка T result; завершится ошибкой. - person Justin; 30.03.2018
comment
ах, я вижу, тогда это, вероятно, кажется лучшим решением :) - person It'sNotALie.; 30.03.2018

Конечно, вы можете сделать это, просто создав временный istream_iterator, например:

arr[*istream_iterator<int>(input)] = something
person Jonathan Mee    schedule 30.03.2018
comment
Я только что обнаружил, что считаю дубликатом этого вопроса, на который не было этого ответа, поэтому я добавил этот ответ туда а также и проголосовал за дублирование этого вопроса. Я расширил свой ответ там, если кто-нибудь захочет проверить его. - person Jonathan Mee; 30.03.2018