C ++: альтернатива STL и Boost? - PullRequest
19 голосов
/ 27 апреля 2011

C ++ - это язык multi-paradigm , а STL и Boost построены на функциональной парадигме языка.STL состоит из контейнеров (для хранения данных), итераторов (для доступа к данным) и алгоритмов (функций для управления данными).Функции алгоритма применяются к контейнерам с использованием итераторов.Как побочный эффект, эти методы не являются частью контейнерных классов, но полностью разделены.(Это позволяет избежать избыточности для авторов библиотек, но болезненно для пользователей библиотек.)

Существуют ли в C ++ альтернативы STL / Boost, которые предлагают такие контейнеры в более традиционном объектно-ориентированном варианте?Я ищу строки, векторы, связанные списки, карту, деревья, хеш-таблицы и тому подобное.Контейнеры должны легко наследоваться и расширяться.Для сравнения, расширение классов из STL / Boost - это очень плохая идея , и это из-за замысла их дизайнеров.

PS: Пожалуйста, не используйте место для ответов ниже, чтобы прояснить преимуществаSTL / подталкивания.Я хорошо их знаю!: -)

Ответы [ 8 ]

31 голосов
/ 27 апреля 2011

Многие (большинство!) Более старые библиотеки для C ++ использовали контейнеры, которые намного ближе к тем, которые используются в таких вещах, как Java и C #.

Несколько примеров таких библиотек включают COOL , ET ++ , NIH Class Library и Rogue Wave Tools.h ++ .

Два очка:

  1. Самое большее, это источник вдохновения. Я почти уверен, что прошло не менее 10 лет (а часто и больше, как 20) с момента обновления любого из них. Практически нет шансов, что какой-либо из них даже скомпилируется с любым достаточно текущим компилятором.
  2. Я хочу заявить, что я даю ссылки на них только в ответ на очень конкретный вопрос. Я, безусловно, не рекомендую использовать какой-либо из приведенных выше кодов, и при этом я не рекомендую даже использовать их в качестве вдохновения.

Чтобы быть уверенным, что здесь все ясно, по крайней мере, ИМО:

  • Утверждения в вашем вопросе совершенно ложны.
  • То, что вы пытаетесь сделать, совершенно безумно!
  • Ты зря тратишь время.
  • Написание кода таким способом - очень, очень плохая идея. Просто скажи нет!
  • Если вы будете настаивать на этом, вы станете изгоем.
    1. Даже непрограммисты, которые не совсем понимают почему, начнут сильно ненавидеть вас.
    2. Ваша собака будет использовать вашу обувь и постель в качестве туалета.

Ты сам по себе. Вы были предупреждены!

Скрытые субтитры для юмора с нарушениями: конечно, кое-что из этого должно быть юмористическим - это действительно, очень паршивая идея, хотя

25 голосов
/ 27 апреля 2011

Это позволяет избежать избыточности для авторов библиотеки, но болезненно для пользователей библиотеки.

Я совершенно не согласен с этой предпосылкой.И даже если бы я это сделал, это огромное чрезмерное обобщение, которое не распространяется на каждого пользователя библиотеки.Но в любом случае это субъективное утверждение, поэтому я его проигнорирую.


Существуют ли альтернативы C ++ для STL / Boost, которые предлагают такие контейнеры в более традиционном объектно-ориентированном виде?

...

Контейнеры должны иметь методы, позволяющие манипулировать ими напрямую.(Например, вызывая vector.sort () вместо sort (vector.begin (), vector.end ()).

Конечно. Просто создайте свои собственные контейнеры, которые имеют стандартные контейнеры в качестве данныхвызовы членов и делегатов для них и для алгоритмов по мере необходимости с помощью функций-членов. Реализовать это довольно тривиально:

template<typename T>
class MyVector
{
public:
    void sort()
    {
        std::sort(vec.begin(), vec.end());
    }

    // ...
private:
    std::vector<T> vec;
};

В C ++ нет ничего, что мешало бы вам делать что-то подобное, как ни странно, благодаря мультипарадигмеприрода C ++, с которой вы, похоже, не согласны.

Вы, вероятно, можете использовать объявления private наследования и using, если вы предпочитаете не писать функции-оболочки.


STL / Boost затрудняет получение из их контейнеров и расширение их.

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

7 голосов
/ 27 апреля 2011

STL и Boost настолько объектно-ориентированы, насколько это возможно.

  1. Для всех теоретических целей функция-член и свободная функция, перегруженные в первом аргументе, - это одно и то же. На практике они ведут себя очень схожим образом, в том числе и для наследования, поэтому в C ++ вы действительно должны рассматривать свободные функции, принимающие (возможно, const) ссылку, в качестве первых аргументов в качестве методов их первого аргумента.

    Преимущество бесплатных функций в том, что они могут быть определены для существующего класса, что позволяет вам добавить интерфейс к существующему классу. Именно поэтому STL и особенно boost используют их так часто. Главное преимущество функций-членов в том, что они могут быть виртуальными (но виртуальные методы должны быть приватными!)

  2. Вы не хотите расширять коллекции путем деривации. Как правило, вы не хотите расширять что-либо путем деривации, если это не абстрактный базовый класс, специально разработанный для него. См. этот вопрос о преимуществах композиции перед наследованием .

6 голосов
/ 27 апреля 2011

Вы идете не в ту сторону.Если вы хотите программировать на Java, то программируйте на Java.Если вы программируете на C ++, то программируйте так, как это делают программисты на C ++.Всегда плыви по течению, никогда против него.

3 голосов
/ 27 апреля 2011

Взгляните на подход Qt4 , я всегда был его поклонником.

обновил ссылку.

1 голос
/ 14 марта 2017

Немного опоздал на эту вечеринку, и я знаю, что ОП специально просит не "понтифицировать", как они уже знают о STL, однако ...

Есть старый Доктор. Интервью Доббса с Алексом Степановым, пионером в области общего программирования и основным участником STL. Очень поучительно несколько способов, особенно для решения вопроса о том, почему более стандартные методы ОО не используются в STL. Выделяется один абзац:

Даже сейчас наследование C ++ не очень полезно для общего программирования. Давайте обсудим почему. Многие люди пытались использовать наследование для реализации структур данных и контейнерных классов. Как мы теперь знаем, было мало успешных попыток. Наследование в C ++ и связанный с ним стиль программирования резко ограничены. Невозможно реализовать дизайн, который включает в себя столь же тривиальную вещь, как равенство, используя его. Если вы начнете с базового класса X в корне вашей иерархии и определите для этого класса оператор виртуального равенства, который принимает аргумент типа X, то выведите класс Y из класса X. Каков интерфейс равенства? Он имеет равенство, которое сравнивает Y с X. Используя животных в качестве примера (ОО люди любят животных), определяют млекопитающих и выводят жирафов из млекопитающих. Затем определите сопряжение функции-члена, где животное соединяется с животным и возвращает животное. Затем вы получаете жирафа от животного, и, конечно, у него есть функция сопряжения, где жираф спаривается с животным и возвращает животное. Это определенно не то, что вы хотите. Хотя спаривание не может быть очень важным для программистов на C ++, равенство есть. Я не знаю ни одного алгоритма, где какое-либо равенство не используется.

Для тех, кто предпочитает ответ Java на эту же головоломку, Джош Блох прилагает все усилия, чтобы изложить те же моменты в «Эффективной Java», пункт 8: соблюдайте общий контакт при переопределении.

Это хорошая глава, с хорошим примером того, как пытаться сохранить контракт равных, в то же время расширяя простой класс Point с добавленным цветом: класс ColorPoint. Далее он демонстрирует, что существует фундаментальное ограничение ООП: нет способа расширить инстанцируемый класс И добавить компонент-значение при сохранении контракта равных .

Конечно, утверждение Блоха сформулировано более кратко, но они оба (правильно) делают одни и те же выводы. Основное отличие состоит в том, что Java является (был) языком «чистого ОО» - все должно находиться в классе, даже те вещи, как алгоритмы, которые не являются объектами естественного характера.

И я думаю, что Блох может быть чувствителен к этой проблеме, потому что он видел, как она эффектно провалилась в библиотеке Java: наследование стека от Vector является одним из примеров заметной проблемы проектирования в Java.

Чуть позже в интервью Степанов продолжает:

Я принимал участие в нескольких дискуссиях в Bell Labs по поводу разработки шаблонов и довольно бурно спорил с Бьярне, что он должен делать шаблоны C ++ как можно более близкими к дженерикам Ada. Я думаю, что я так сильно спорил, что он решил против этого Я понял важность наличия шаблонных функций в C ++, а не просто шаблонных классов, как считали некоторые люди. Однако я подумал, что шаблонные функции должны работать как дженерики Ada, то есть они должны быть явно созданы. Бьярне не слушал меня и разработал механизм функций шаблонов, в котором шаблоны создаются неявно с использованием механизма перегрузки. Эта конкретная техника стала решающей для моей работы, потому что я обнаружил, что она позволяет мне делать много вещей, которые были невозможны в Аде. Я рассматриваю этот конкретный дизайн Бьярна как чудесную работу, и я очень рад, что он не последовал моему совету.

0 голосов
/ 16 августа 2013

То, что Dilawar заявил, на самом деле является решением для всех ваших потребностей контейнера.

Используйте Boost :: graph или аналогичную реализацию. Вы можете использовать его [это то, что я делаю] в качестве системы управления объектами.

Что касается критики STL, то это вопрос вкуса, а не технических возражений. Они существуют, но не на этом уровне.

0 голосов
/ 23 июля 2013

Почему бы не использовать граф вместо контейнеров STL и прикрепить то, что вам нужно, к узлам или ребрам. Они могут имитировать любые контейнеры STL (я не прав?). Вы можете легко перебирать узлы или ребра (DFS, BFS) и по ходу дела делать то, что вам нравится делать с данными, прикрепленными к узлам и ребрам. Легкое сочетание алгоритма и итератора, не так ли?

...