Как вернуть значение std::copy в случае успеха или неудачи?

Я использую std::copy для копирования объектов из std::deque в файл. Код работает нормально, но мне нужно проверить, было ли копирование успешным, и, соответственно, мне нужно установить флаг или выдать исключение.

Я гуглил, но не смог найти решение, как проверить, успешно ли std::copy скопировал значения в файл.

Может кто-нибудь, пожалуйста, пролить свет на это.


person samantha    schedule 13.03.2012    source источник
comment
Разве вы не можете просто проверить состояние потокового ввода-вывода?   -  person Some programmer dude    schedule 13.03.2012


Ответы (2)


Если запись в файл не удалась, будут установлены флаги ошибок файлового потока — вы можете либо проверить их после копирования, либо сначала вызвать функцию-член exceptions, чтобы она выдавала исключение при ошибке. Если что-то еще не удается, будет выброшено исключение.

person Mike Seymour    schedule 13.03.2012

Алгоритм AFAIK std::copy ничего не проверяет, а просто перебирает все элементы и копирует их в выходной итератор. Это означает, что вы должны самостоятельно предоставить достаточно места в выходном итераторе, иначе поведение не указано.

Поэтому в вашем случае вы должны сами проверить, что выходной файл доступен для записи и т. д. Один из возможных способов проверить это, я думаю, использовать флаги ошибок для используемого вами файлового потока, т.е. после копирования проверьте, что ваш ofstream является good (вы для этого можно использовать функции good(), eof(), fail() и bad()).

Второй подход заключается в проверке возвращаемого значения std::copy. Поскольку он возвращает итератор в конец диапазона назначения (который указывает на элемент, следующий за копией последнего), вы можете вычислить разницу между возвращаемым значением std::copy и вашим выходным итератором и убедиться, что он равен размеру ваш deque. Например. (псевдокод)

OutputIterator result = std::copy(input.begin(), input.end(), output);
assert(result - output == input.end() - input.begin());

EDIT: Второй подход работает только тогда, когда output также является типом итератора ввода, поэтому std::distance работает для него. Правильнее будет написать:

assert(std::distance(output, result) == std::distance(input.begin(), input.end()));
person Artak Begnazaryan    schedule 13.03.2012
comment
Конечно, вы не можете использовать второй подход с std::ostream_iterator, так как это итератор вывода, std::distance тоже не будет работать. - person Christian Rau; 13.03.2012
comment
Да, ты прав. Второй подход будет работать только тогда, когда output также является итератором ввода. - person Artak Begnazaryan; 13.03.2012