Подтвердить что ты не робот

Анонимные пространства имен: они действительно такие замечательные?

Я использую ключевое слово static долгое время для определения внутренней привязки. Позже я переключился на стиль С++ для обертывания локальных вещей в анонимных пространствах имен.

Однако теперь, когда я работал с анонимными пространствами имен в течение нескольких лет, я начинаю думать, что ключевое слово static намного проще работать с!

Общей проблемой является то, что у меня есть этот шаблон:

namespace {
    // ...five pages of code...
}  // namespace

Чтобы узнать, есть ли у какой-либо функции внутренняя или внешняя связь, теперь мне приходится много прокручивать, в отличие от старого стиля C, где я мог бы просто проверить, была ли перед этим функция/объект static.

Я знаю, что есть вещи, которые анонимные пространства имен делают, что static не может - скрывать typedefs, но лично меня это не очень интересует. Во всяком случае.

Как вы относитесь к этому? Является ли выигрыш анонимных пространств имен большим, что он гарантирует снижение читаемости? Или я ошибаюсь?

4b9b3361

Ответ 1

Если код в вашем пространстве имен слишком длинный, вам нечего остановить:

namespace {
    int foo(char* x) {
        return x[0] + x[1];
    }
}

namespace {
    int bar(char *x, char *y) {
        return foo(x) + foo(y);
    }
}

В С++ 03 практическое преимущество использования неназванного пространства имен заключается именно в том, что содержимое имеет внешнюю связь (но все еще невидимо вне TU, потому что нет способа ссылаться на них). Параметры шаблона не могут иметь внутренней связи:

namespace {
    int foo(const char* x) {
        return x[0] + x[1];
    }
}

static int foo2(const char *x) {
    return x[0] + x[1];
}

template <int (*F)(const char*)>
void baz(const char *p) {
    F(p);
}

int main() {
    baz<foo>("ab");   // OK
    baz<foo2>("ab");  // not valid
}

Ответ 2

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

Предположим, что у вас есть одна или две функции класса, для которых требуется несколько других вспомогательных функций, которые являются весьма конкретными, но не используют членов класса. Если вы придерживаетесь Роберта К. Мартина (функции должны быть небольшими и служить одной четко определенной цели), вы часто обнаружите, что большие функции могут быть реорганизованы на более мелкие, хотя эти меньшие могут вначале использоваться только в бывшей большой функции.

Итак, какие у вас параметры:

  • Внесите новый (возможно, частный) класс сразу:

    Это влечет за собой довольно много печатания, возможно, слишком много, и -lets сталкиваются с этим - все иногда ленив или спешит.

  • Генерировать частные статические функции или функции, не являющиеся членами:

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

  • Анонимное пространство имен:

    У вас есть вспомогательная функция, которая не нужна членский доступ и служит одной цели → Положите его и напишите функции, близкой к методам класса, в которой он будет использоваться. Это большой мой предпочтительный: он быстрый, и он не загромождает файл заголовка. В пространстве имен четко указано: это не используется ничем другим, кроме этого cpp. нет друг будет использовать его, и ни один пользователь библиотеки никогда не узнает об этом. Вы вряд ли может быть более очевидным, и часто эта парадигма приведет к более чистое функционирование, которое имеет несколько входных параметров и только один выход модифицировано. Кроме того, у вас есть функция: Определить непосредственно перед первичным использовать. Хотя это может быть недостатком, я считаю, что это очень полезно при просмотре реализация больших классов. Другим преимуществом являются константы, которые охватывают несколько но не очень интересны для пользователя библиотеки. Поместите их в пространство имен также лучше всего работает с функциями, которые их используют. Если это повернется что вам нужны константы и функции в другом месте, преобразуйте целое в класс, его уже аккуратно упакованы.

Отказ от ответственности: многие люди могут утверждать, что использование пимпла намного чище. Это только мое личное мнение.

Ответ 3

Анонимное пространство имен - единственное, что не позволяет объявлению класса загрязнять глобальную область. Очень полезно при определении класса в файле .cpp.