В списке std-предложений был указан следующий код:
#include <vector>
#include <algorithm>
void foo(const std::vector<int> &v) {
#ifndef _ALGORITHM
std::for_each(v.begin(), v.end(), [](int i){std::cout << i; }
#endif
}
Пусть игнорирует, для целей этого вопроса, почему этот код был дано и почему он был написан таким образом (так как была веская причина, но это не имело значения здесь). Он предполагает, что _ALGORITHM
является защитой заголовка внутри стандартного заголовка <algorithm>
, который поставляется с известной реализацией стандартной библиотеки. Здесь нет неотъемлемого намерения переносимости.
Теперь _ALGORITHM
будет, конечно, зарезервированным именем, за:
[C++11: 2.11/3]:
Кроме того, некоторые идентификаторы зарезервированы для использования реализацией С++ и стандартными библиотеками (17.6.4.3.2) и не должны использоваться иначе; диагностика не требуется.
[C++11: 17.6.4.3.2/1]:
Определенные наборы имен и сигнатур функций всегда зарезервированы для реализации:
- Каждое имя, содержащее двойной знак подчеркивания
_ _
или начинающийся с символа подчеркивания, за которым следует заглавная буква (2.12), зарезервировано для реализации для любого использования.- Каждое имя, начинающееся с символа подчеркивания, зарезервировано для реализации для использования в качестве имени в глобальном пространстве имен.
У меня всегда создавалось впечатление, что цель этого отрывка состояла в том, чтобы помешать программистам определять/мутировать/не определять имена, которые подпадают под вышеуказанные критерии, так что разработчики стандартной библиотеки могут использовать такие имена, не опасаясь конфликтов с клиентом код.
Но в списке std-предложений было заявлено, что этот код сам плохо сформирован, просто ссылаясь на такое зарезервированное имя. Теперь я могу видеть, как использование фразы "не должно использоваться иначе" из [C++11: 2.11/3]:
может действительно предположить, что.
Одно практическое обоснование заключалось в том, что макрос _ALGORITHM
мог бы расширяться до некоторого кода, который стирает ваш жесткий диск, например. Однако, принимая во внимание вероятное намерение этого правила, я бы сказал, что такая вероятность имеет больше общего с очевидным, определяемым реализацией * характером названия _ALGORITHM
, и меньше делать с ним прямое противозаконное обращение к нему.
* "определенная реализация" в своем смысле на английском языке, а не в стандартном смысле С++ фразы
Я бы сказал, что до тех пор, пока мы будем рады, что у нас будут определенные результаты, и мы должны исследовать, что этот макрос означает для нашей реализации (если он вообще существует!), он не должен по своей сути нелегально ссылаться на такой макрос, если мы не пытаемся его модифицировать.
Например, код, такой как следующий, используется повсюду, чтобы различать код, скомпилированный как C и код, скомпилированный как С++:
#ifdef __cplusplus
extern "C" {
#endif
и я никогда не слышал об этом жалобе.
Итак, что вы думаете? "Нельзя ли использовать иначе", просто написать такое имя? Или это, вероятно, не так строго (что может указывать на возможность настройки стандартной формулировки)?