Будет ли использование директивы препроцессора для определения того, что символ доллара представляет конфликт?
Могу ли я использовать следующее в C++?
#define $ cout
int main(){
$<<"Hello World!\n";
return 0;
}
Мне интересно, не вызовет ли это каких-либо конфликтов.
3 ответа
Это не совсем законно, но ваша реализация может принять это.
Рассматривать:
[C++11: 2.5/1]:
Каждый токен предварительной обработки, который преобразуется в токен (2.7), должен иметь лексическую форму ключевого слова, идентификатора, литерала, оператора или пунктуатора.
Здесь ваш $
очевидно, не является ключевым словом, оператором или пунктуатором (так как они перечислены в стандарте), и не выглядит как литерал, так что это может быть только идентификатор; теперь идентификаторы должны содержать только буквенно-цифровые и подчеркивания, а цифры не могут быть начальными (на основе грамматики, обозначенной как [C++11: 2.11]
).
Тем не менее, стандарт также позволяет реализациям принимать другие символы, так что то, что вы хотите сделать, может работать, но оно не будет переносимым.
Это поведение, определяемое реализацией. $
не входит в грамматику для идентификаторов, правила для имен идентификаторов в C++:
- Не может начинаться с цифры
- Может состоять из букв, цифр, подчеркивания, имен универсальных символов и символов, определенных для реализации
- Не может быть ключевым словом.
Но он допускает символы, определенные реализацией, которые многие компиляторы поддерживают как расширение, включая gcc и Visual Studio.
Фактическая грамматика описана в разделе стандарта C++. 2.11
Идентификатор:
identifier:
identifier-nondigit <- Can only start with a non-digit
identifier identifier-nondigit <- Next two rules allows for subsequent
identifier digit <- characters to be those outlined in 2 above
identifier-nondigit:
nondigit <- a-z, A-Z and _
universal-character-name
other implementation-defined characters
[...]
Мы можем видеть, что это относится к define
из раздела 16
Директивы предварительной обработки. Из грамматики видно, что это должен быть идентификатор:
# define identifier replacement-list new-line
# define identifier lparen identifier-listopt) replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list, ... ) replacement-list new-line
^^^^^^^^^^
Забавная ситуация с некоторыми компиляторами, которые позволяют использовать $
в идентификаторах. Например как минимум MS VC++ 2010 позволяет использовать $
в идентификаторах.
Так что если, например, вы определили
char $ = '$';
а потом написал
#define $ std::cout
//...
$ << $;
тогда вместо символа $ вы увидите в консоли вывод № 1 или какое-то целое число.:)