Подтвердить что ты не робот

Основные и второстепенные макросы, определенные в 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)

4b9b3361

Ответ 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' является закрывающей скобкой, поэтому он не является вызовом макроса.