Основные и второстепенные макросы, определенные в sys/sysmacros.h, втянутые в <iterator>
Я пишу класс с матричной структурой, и я хочу, чтобы функция-член с именем minor была такой же, как операция с матрицей. Это вызывает некоторые ошибки. Минимальный тестовый пример в моей системе:
#include <iterator>
void minor(int row, int col);
При компиляции clang предоставляет следующую ошибку:
$ clang++ -Weverything -std=c++11 test.cpp
test.cpp:2:21: error: too many arguments provided to function-like macro invocation
void minor(int row, int col);
^
/usr/include/x86_64-linux-gnu/sys/sysmacros.h:67:10: note: macro 'minor' defined here
# define minor(dev) gnu_dev_minor (dev)
^
test.cpp:2:6: error: variable has incomplete type 'void'
void minor(int row, int col);
^
2 errors generated.
$
Соответствующая часть sys/sysmacros.h:
/* Access the functions with their traditional names. */
# define major(dev) gnu_dev_major (dev)
# define minor(dev) gnu_dev_minor (dev)
# define makedev(maj, min) gnu_dev_makedev (maj, min)
Очевидно, что эти конкретные макросы могут быть # undef'd, но кажется довольно глупым, что такие рутинные слова, как майор и минор, будут определяться как макросы, в частности, когда вы занимаетесь частью стандартной библиотеки С++. Есть ли какая-то причина, которая должна быть определена? Это ошибка в стандартной библиотеке, которую я использую? (libstdС++ 4.8.2, как и при тестировании Debian)
Ответы
Ответ 1
В соответствии со стандартом С++ эти имена не должны быть зарезервированы для реализации и, следовательно, доступны.
Согласно man 3 makedev
:
Функции makedev(), major() и minor() не указаны в POSIX.1, но присутствуют во многих других системах
и
Эти интерфейсы определяются как макросы. Поскольку glibc 2.3.3, они были псевдонимами для трех функций, специфичных для GNU: gnu_dev_makedev(), gnu_dev_major() и gnu_dev_minor(). Последний имена экспортируются, но традиционные имена более переносимы.
Кажется, что они не удалены для обратной совместимости (например, https://bugzilla.redhat.com/show_bug.cgi?id=130601).
Я думаю, вы могли бы #undef их без серьезных проблем (многие проекты выполняются таким образом).
С g++/CLANG/MSVC вы также можете сделать что-то вроде:
#pragma push_macro("minor")
#undef minor
// do what you need
#pragma pop_macro("minor")
Это некрасиво, но помогает с именованием конфликтов.
Кроме того, в зависимости от того, как структурирован ваш код, этот трюк может быть полезен:
#define minor(dev) gnu_dev_major(dev)
void (minor)(int row, int col) { /* ... */ }
В строке определения функции символ после 'minor' является закрывающей скобкой, поэтому он не является вызовом макроса.