как пересылать-объявить std :: set в c ++? - PullRequest
2 голосов
/ 17 июня 2020

Чтобы ускорить процесс компиляции, я пытаюсь упростить свой заголовочный файл MyClass.hpp путем прямого объявления контейнеров STL, таких как std :: vector, std :: set ...

Но std::set может НЕ быть объявлено вперед в следующих кодах, а std::vector может быть.

namespace std {
    template<typename T, typename A> class vector;
    template<typename T, typename C, typename A> class set;
};

class MyClass_t {
        void showVector( std::vector<int>& );
        void showSet( std::set<int>& );
}

Как известно, заголовок очень длинный и сложный. Если мы добавим #include <set> в MyClass.hpp, фактически каждая единица перевода, которая использует MyClass_t, должна неявно включать заголовок . Но я думаю, что в этом нет необходимости, потому что не все единицы перевода, использующие MyClass_t, будут вызывать MyClass_t::showSet, поэтому я думаю, что упрощение имеет смысл.

Как это сделать?

Заранее спасибо, пожалуйста, простите мою бедную Энгли sh.

1 Ответ

0 голосов
/ 17 июня 2020

Одна из целей пространств имен - разделить код, поступающий из разных источников. Часто думают, чтобы избежать конфликтов имен, но это идет на более глубокий уровень.

Когда библиотека определяет пространство имен, она (обычно) заявляет, что полностью владеет им. Библиотека оставляет за собой право изменять любые и все аспекты всего, что определено в пространстве имен, обычно гарантируя только API publi c. Это распространяется на предварительные объявления. Любые форвардные объявления в пространстве имен являются доменом библиотеки, если не указано иное, поскольку библиотека может захотеть что-то изменить за кулисами. Некоторые библиотеки относятся к этому серьезно и предоставляют заголовки прямого объявления, но без них вам не повезло.

В общем, не ожидайте, что вы сможете пересылать объявление чего-либо, что вы не контролируете. Даже если он работает изначально, он может сломаться при любом обновлении / исправлении библиотеки.


Переходя к std::set, пространство имен std зарезервировано для стандартной библиотеки. Стандартная библиотека предоставляет вам возможность объявлять некоторые вещи в пространстве имен std в ограниченных обстоятельствах, но в остальном это для вас запрещено. К сожалению для вашей цели, стандартная библиотека не требует заголовков прямого объявления. Если вы хотите, чтобы ваш код был кроссплатформенным и / или стабильным после обновления компилятора, вам нужно будет включить полный заголовок. to namespace std - неопределенное поведение. Дело не в том, что такие вещи гарантированно что-то сломают, а в том, что языковой стандарт не может гарантировать, что именно сломает. (На самом деле, если вы определили класс с именем supercalifragilisticiwillmisspellthis в namespace std, вероятно, ничего не взорвется.) Для простоты применяется метка «неопределенное поведение» и реализациям предоставляется максимальная свобода.

...