Экспериментальное пространство им.

Является ли это плохим или хорошим parctice, чтобы ввести пространство имен std::experimental в std, как показано ниже?

namespace std
{
namespace experimental
{
}
using namespace experimental;    
}

#include <experimental/optional>

int main()
{
    std::optional< int > o;
    return 0;
}

Или даже в более современном виде:

#if __has_include(<optional>)
# include <optional>
#elif __has_include(<experimental/optional>)
# include <experimental/optional>
namespace std
{
using namespace experimental;    
}
#else
#error !
#endif

int main()
{
    std::optional< int > o;
    return 0;
}

Намерение ввести подпространство std::experimental "понятно, потому что std::experimental в настоящее время содержит множество новых библиотек. Я думаю, что очень вероятно, что все они перейдут на namespace std без каких-либо существенных изменений, и написанный в настоящее время код пользователя может положиться на это (я совершенно не прав?). В противном случае весь этот код должен быть реорганизован для перехода от std::experimental:: в std:: в будущем. Это не имеет большого значения, но могут быть причины не делать этого.

Вопрос касается как производственного кода, так и не слишком серьезного кода.

Ответ 1

Звучит неплохо.

Во-первых, это поведение undefined. В стандарте N4140 говорится:

[namespace.std]/1: Поведение программы на С++ undefined, если оно добавляет объявления или определения в пространство имен std или в пространство имен в пространстве имен std, если не указано иное. [...]

Использование-директива - это своего рода декларация, поэтому UB - это порядок дня.

Во-вторых, вещи в std::experimental очень подвержены изменениям. Вы можете обнаружить, что когда вещи перемещаются в std правильно, что ваш код все еще компилируется, но не действует совершенно так же. Это просто вызывает проблемы, особенно в производственном коде.

Ответ 2

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

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

Прохождение кода для удаления std:: experimental (или изменения в std:: или std:: something_else) - это просто замена текста. В лучшем случае вы смотрите на быструю команду в своем редакторе или идее. В худшем случае вы планируете провести пару часов, написав регулярное выражение - возможно, в вашем редакторе, возможно, в PERL или Ruby...

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

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

Ответ 3

То, что вы делаете, вводит поведение undefined. В общих чертах, я бы сказал, что введение поведения undefined в большей степени относится к сфере плохой практики, чем к практике хорошей практики.

В соответствии со стандартом С++ 1998 года, раздел 17.4.3.1, пункт 1.

Это undefined для программы на С++ для добавления объявлений или определений в пространство имен std или пространства имен в пространстве имен std, если не указано иное указано. Программа может добавлять специализированные шаблоны для любого стандарта шаблон библиотеки в пространство имен std. Такая специализация (полная или частично) стандартного шаблона библиотеки приводит к поведению undefinedесли декларация не зависит от пользовательского имени внешнего и если специализация не соответствует стандартной библиотеке требования к исходному шаблону.

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

Ответ 4

Многие библиотеки в std::experimental могут и будут изменяться способами, которые нарушают код пользователя до перехода на std, и они могут даже не мигрировать в std. Вот почему они помещают их в std::experimental.

std::experimental предназначен для относительно свободного места, где вы можете ввести новые предлагаемые библиотечные функции для С++, а компиляторы могут реализовать их, не нарушая существующий код. Реализации находятся в потоке и не являются стандартными. Некоторые из них могут перейти на С++ 1z, но некоторые из них могут не быть, а те, которые делают это, могут быть изменены, а те, которые не делают этого, могут сделать его на С++ 2x с существенными изменениями.

Просто посмотрите на историю, скажем, диапазонов. Или предлагает сопрограммы/возобновляемые функции, которые предлагает Microsoft. Или рабочая группа по отражению. Или понятия.

Цель этой итерации С++ - это, смею сказать, быть Agile и быстро выходить из строя. Многие независимые предложения прокладывают себе путь через трубопровод с целью минимизации взаимозависимостей. Если данное предложение не готово к прайм-тайму в то время, когда существует стандарт С++, он не вносит его. Если он готов и стоит, он добавляется модульно.

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

В дополнение к вышеизложенному, возиться с std таким образом делает вашу программу плохо сформированной без необходимости диагностики, как указывали другие ответы.