Почему классы std :: fstream не принимают std :: string? - PullRequest
34 голосов
/ 28 августа 2008

На самом деле это не вопрос дизайна, хотя может показаться, что это так. (Ну, ладно, это своего рода вопрос дизайна). Мне интересно, почему классы C ++ std::fstream не принимают std::string в своих конструкторах или открытых методах. Все любят примеры кода так:

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::string filename = "testfile";      
    std::ifstream fin;

    fin.open(filename.c_str()); // Works just fine.
    fin.close();

    //fin.open(filename); // Error: no such method.
    //fin.close();
}

Это заставляет меня все время работать с файлами. Конечно, библиотека C ++ будет использовать std::string везде, где это возможно?

Ответы [ 10 ]

26 голосов
/ 01 сентября 2008

Взяв строку C, класс C ++ 03 std::fstream уменьшил зависимость от класса std::string. Однако в C ++ 11 класс std::fstream разрешает передавать std::string для своего параметра конструктора.

Теперь вы можете задаться вопросом, почему не существует прозрачного преобразования из std:string в строку C, поэтому класс, который ожидает строку C, все равно может принять std::string точно так же, как класс, который ожидает std::string может взять строку C.

Причина в том, что это приведет к циклу преобразования, что, в свою очередь, может привести к проблемам. Например, предположим, что std::string можно преобразовать в строку C, чтобы вы могли использовать std::string s с fstream s. Предположим также, что строка C конвертируется в std::string s, как и состояние в текущем стандарте. Теперь рассмотрим следующее:

void f(std::string str1, std::string str2);
void f(char* cstr1, char* cstr2);

void g()
{
    char* cstr = "abc";
    std::string str = "def";
    f(cstr, str);  // ERROR:  ambiguous
}

Поскольку вы можете преобразовать любой путь между std::string и строкой C, вызов f() может разрешиться в любую из двух f() альтернатив, и поэтому является неоднозначным. Решение состоит в том, чтобы разорвать цикл преобразования, сделав одно направление преобразования явным, что STL решил сделать с c_str().

14 голосов
/ 28 августа 2008

Есть несколько мест, где комитет по стандартизации C ++ действительно не оптимизировал взаимодействие между средствами в стандартной библиотеке.

std::string и его использование в библиотеке является одним из них.

Еще один пример - std::swap. Многие контейнеры имеют функцию-член swap, но перегрузка std :: swap не предоставляется. То же самое касается std::sort.

Я надеюсь, что все эти мелочи будут исправлены в следующем стандарте.

11 голосов
/ 15 сентября 2008

Возможно, это утешительно: все fstream получили открытое (string const &, ...) рядом с открытым (char const *, ...) в рабочем проекте стандарта C ++ 0x. (см., например, 27.8.1.6 для описания basic_ifstream)

Так что, когда он будет доработан и реализован, он вас больше не получит:)

9 голосов
/ 16 сентября 2008

Библиотека потокового ввода-вывода была добавлена ​​в стандартную библиотеку C ++ до STL. Чтобы не нарушать обратную совместимость, было решено избегать изменения библиотеки ввода-вывода при добавлении STL, даже если это означало некоторые проблемы, такие как та, которую вы подняли.

3 голосов
/ 15 сентября 2008

@ Бернард:
Монолиты "Unstrung". «Все за одного и один за всех» могут работать для мушкетеров, но это не так хорошо работает для классных дизайнеров. Вот пример, который не совсем примерный, и он показывает, насколько сильно вы можете ошибиться, когда дизайн превращается в чрезмерный дизайн. Пример, к сожалению, взят из стандартной библиотеки рядом с вами ... ~ http://www.gotw.ca/gotw/084.htm

2 голосов
/ 28 августа 2008

Это несущественно, это правда. Что вы подразумеваете под большим интерфейсом std :: string? Что означает большое в этом контексте - много вызовов методов? Я не шутливый, мне на самом деле интересно.

У него больше методов, чем нужно, и его поведение с использованием интегральных смещений, а не итераторов, немного сомнительно (поскольку это противоречит принципам работы остальной библиотеки).

Реальная проблема в том, что библиотека C ++ состоит из трех частей; у него есть старая библиотека C, у него есть STL, и у него есть строки-и-iostreams. Хотя были предприняты некоторые усилия для объединения различных частей (например, добавление перегрузок в библиотеку C, поскольку C ++ поддерживает перегрузку; добавление итераторов к basic_string; добавление адаптеров итераторов iostream), при посмотрите на детали.

Например, basic_string включает методы, которые являются ненужными дубликатами стандартных алгоритмов; различные методы поиска, вероятно, могут быть безопасно удалены. Другой пример: в локалях вместо итераторов используются необработанные указатели.

1 голос
/ 11 ноября 2012

C ++ вырос на меньших машинах, чем монстры, которые мы пишем сегодня. Когда iostream был новым, многие разработчики действительно заботились о размере кода (им приходилось помещать всю программу и данные в несколько сотен килобайт). Поэтому многие не хотели использовать «большую» библиотеку C ++. Многие даже не использовали библиотеку iostream по тем же причинам, размер кода.

У нас не было тысяч мегабайт оперативной памяти, которые мы можем использовать, как сегодня. У нас обычно не было связывания на уровне функций, поэтому мы были в зависимости от разработчика библиотеки, который использовал много отдельных объектных файлов или извлекал тонны неиспользуемого кода. Все это FUD заставило разработчиков держаться подальше от std :: string.

Тогда я тоже избегал std :: string. "Слишком раздутый", "слишком часто вызывается" malloc "и т. Д. Глупо использовать буферы на основе стеков для строк, а затем добавлять все виды утомительного кода, чтобы убедиться, что он не переполняется.

0 голосов
/ 10 марта 2016

В настоящее время вы можете решить эту проблему очень легко: добавьте -std=c++11 к вашему CFLAGS.

0 голосов
/ 28 августа 2008

Я считаю, что об этом думали и делали, чтобы избежать зависимости; то есть #include не должно заставлять #include .

Если честно, это кажется несущественной проблемой. Лучше спросить: почему интерфейс std :: string такой большой?

0 голосов
/ 28 августа 2008

Есть ли в STL класс, который принимает строку ... Я так не думаю (не смог найти ни одного в моем быстром поиске). Так что, вероятно, это некое дизайнерское решение, что ни один класс в STL не должен зависеть от какого-либо другого класса STL (который напрямую не нужен для функциональности).

...