Как вернуть fstream (C++0x)
Я думаю, что я начну с этого и начну с кода:
#include <iostream>
#include <fstream>
#include <string>
class test : public std::ofstream
{
public:
test(const std::string& filename) { this->open(gen_filename(filename)); };
test(const test&) = delete;
//test(test&& old) = default; // Didn't compile
test(test&& old) {};
private:
std::string gen_filename(const std::string& filename)
{ return filename + ".tmp"; }
};
int main()
{
auto os = test("testfile");
os << "Test1\n";
os << "Test2\n";
}
По сути, мне нужно вернуть оффстрим. Конечно, вы не можете скопировать ofstream, поэтому я возился с кодом в тесте класса, и я получил вышеописанное для компиляции и работы, как вы ожидаете (на gcc 4.5).
Но у меня плохое предчувствие, что это просто из-за того, что мой компилятор выполняет "Оптимизацию возвращаемого значения" (RTO) для "auto os = test()". Действительно, если изменить следующее:
int main()
{
auto os = test("testfile");
os << "Test1\n";
auto os2 = std::move(os);
os2 << "Test2\n";
}
Я больше не получаю оба Test1 и Test2 в выводе.
Дело в том, что класс "test" не копируется, поэтому вероятность дублирования ofstream отсутствует. Я просто хочу иметь возможность вернуть его из функции. И я, кажется, могу сделать это с GCC.
Я бы предпочел не разыменовывать умные указатели в куче, выделенной из потока, или повторно открывать файл, так как в настоящее время он работает без этих действий. У меня просто ощущение, что я немного "нестандартен" в своем подходе, поэтому стандартный способ сделать то, что я описал, был бы великолепен.
3 ответа
Я собираюсь ответить на свой вопрос здесь:
На странице Особенности библиотеки GCC C++0x посмотрите на пункт 27.9, который гласит:
27.9 - Файловые потоки - Частично - Отсутствуют операции перемещения и обмена
Я думаю, что это, вероятно, проблема, которую я имею с GCC.
Проблема с этим:
test(test&& old) {};
Это позволяет вам построить новый test
от ценности test
Да, но это ничего не говорит о вашей базе, которая просто создается по умолчанию (нет открытого файла). То, что вы хотите, это:
test(test&& old) : std::ofstream(std::move(old)) {};
Который будет перемещать поток из old
в базу.
Должен ли звонящий знать, что вы возвращаете ofstream
или было бы более разумным вернуть streambuf
и позволить вызывающей стороне обернуть его в потоке?