нет стандартного пространства имен

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

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

#include <vector>
#include <set>
#if defined(NO_STD_LIB)
    #include <iostream.h>
#else
    #incude <iostream>

    using std::string;
    using std::cout;
    using std::vector;
    using std::cout;
#endif

Вы используете это следующим образом

#include stl.h
int main() {
    vector<string> foo;
    .....
    return 0;
}

При таком подходе есть 2 основные проблемы:

  1. Каждая единица компиляции, включающая std.h, должна компилировать много ненужного кода (и мы пытаемся максимально сократить время компиляции в минуту).
  2. Глобальное пространство имен загрязняется почти всем, что обычно находится в пространстве имен std.

Я действительно хотел бы рассмотреть оба этих момента в рамках проекта по очистке кода. Первая действительно является более важной причиной для этого.

Поскольку мы должны поддерживать этот старый компилятор, наш код всегда должен будет избегать конфликтов имен с вещами, которые он предоставляет в своей стандартной библиотеке, поэтому пункт 2 на самом деле не актуален, хотя я хотел бы увидеть решение, которое работает, когда / если мы наконец сможем отказаться от его поддержки.

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

Я думаю, что это решит проблему 1 достаточно легко.

Моя настоящая проблема - исправить проблему 2. Я думал сделать что-то вроде этого

#if defined(NO_STD_LIB)
    #include <iostream.h>
    #define std
#else
    #include <iostream>

тогда мы могли бы кодировать следующим образом:

#incude "stl_iostream"

int main() {
  std::string foo("bar");
  std::cout << foo << std::endl;
}

И это почти сработало. Там, где не было стандартного пространства имен, #define std заставлял std::string разлагаться на ::string, и жизнь была хороша.

Затем я попробовал это с файлом .cc, в котором использовалось ужасное «использование пространства имен std;» и я получаю ошибку компиляции, потому что это становится «использованием пространства имен», так что, очевидно, это не сработает.

Теперь, очевидно, я мог бы запретить людям писать «используя пространство имен std;», но, хотя этого следует избегать в заголовках, иногда это полезно в файлах .cc, где вы интенсивно используете множество классов STL.

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

Я думал об использовании предварительно скомпилированных заголовков для решения проблемы скорости компиляции, но мы нацелены на разные компиляторы, и усилия, направленные на то, чтобы заставить это работать во всех них, могут означать, что это не стоит нашего времени.

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


person Glen    schedule 20.12.2009    source источник


Ответы (1)


Можешь попробовать:

#if defined(NO_STD_LIB)
namespace std {
    using ::string;
    using ::cout;
    using ::vector;
    using ::cout;
}
#endif

Тогда std::string будет работать.

Было бы намного лучше, если бы в языке существовала директива using namespace ::;; однако это не так.

person Thomas Bonini    schedule 20.12.2009