由<iterator>引入的sys/sysmacros.h中定义的主要和次要宏

Wil*_*ill 17 c++ macros glibc libstdc++

我正在编写一个具有类似矩阵结构的类,我希望有一个名为minor的成员函数与矩阵操作相同.这会触发一些错误.我系统上的最小测试用例:

#include <iterator>
void minor(int row, int col);
Run Code Online (Sandbox Code Playgroud)

编译时,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.
$
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

很明显,这些特定的宏可能是#undef'd,但似乎很愚蠢,像major和minor这样的常规单词将被定义为宏,特别是在拉入部分C++标准库时.有什么理由需要定义吗?这是我正在使用的标准库中的错误吗?(在Debian测试中的libstdc ++ 4.8.2)

man*_*lio 14

根据C++标准,这些名称不应保留给实现,因此可用.

根据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")
Run Code Online (Sandbox Code Playgroud)

这很难看,但有助于命名冲突.

此外,根据代码的结构,这个技巧可能很有用:

#define minor(dev) gnu_dev_major(dev)

void (minor)(int row, int col) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

在函数定义行中,'minor'后面的字符是一个右括号,因此它不是宏调用.