Почему <cmath>
предоставляет объекты вне пространства имен std?
Из-за истории.
<cmath>
заголовок является заголовком, унаследованным от C стандартная библиотека (где она называется <math.h>
). В языке C существует только глобальное пространство имен 1 , в котором объявлены все имена.
Поскольку многие реализации C ++ также являются реализациями C, они часто реализуют унаследованные * 1050. * стандартный заголовок, включающий его как есть 2 , что означает, что он объявляет глобальные имена.
Хотя могут существовать методы, позволяющие избежать (за исключением стандартных макросов) объявления глобальных имен, он маловероятно, что реализации, которые делали это до стандартизации, изменили бы поведение, потому что это нарушило бы обратную совместимость.
Не работает ли моя стандартная библиотека?
Нет. Стандарт C ++ позволяет это; Все стандартные имена библиотек C зарезервированы для этого (или любого) использования языковой реализацией. Вы не можете определять их самостоятельно.
Могу ли я что-то сделать, чтобы избежать этого?
Вы обычно не можете запретить стандартной библиотеке делать это.
Вы технически можно избежать большей части этого, выбрав использование автономной языковой реализации. Но если вы выберете это, вы потеряете почти всю стандартную библиотеку.
Вы можете минимизировать вероятность конфликта имен, избегая объявления любых глобальных имен самостоятельно, за исключением одного пространства имен с достаточно уникальным именем. Что-то вроде:
namespace usr_bitmask::log {
}
1 Обратите внимание, что понятие "пространство имен" в языке C является чем-то другим.
2 И, кроме того, повторно объявляет имена в пространстве имен std
при использовании именованного заголовка <c...
, а также добавляет специфические для C ++ перегрузки c в некоторых случаях.