major and minor macros defined in sys/sysmacros.h pulled in by <iterator>
Asked Answered
F

1

20

I'm writing a class that has a matrix-like structure and I want to have a member function named minor to be the same as the matrix operation. This triggers some errors. A minimal test case on my system:

#include <iterator>
void minor(int row, int col);

When compiled, clang provides the following error:

$ 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.
$

The relevant portion of sys/sysmacros.h is:

/* 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)

Clearly, these specific macros could be #undef'd, but it seems quite silly that such routine words as major and minor would be defined as macros, particularly when pulling in part of the C++ standard library. Is there some reason these need to be defined? Is this a bug in the standard library I'm using? (libstdc++ 4.8.2 as in Debian testing)

Fatalism answered 7/3, 2014 at 3:41 Comment(2)
Try -std=c++11 -ansiSunup
Adding -ansi gets that minimal testcase to work, but it triggers errors elsewhere in my project, so I can't enable it, at least in the short term. Are there any options other than -ansi?Fatalism
M
17

According to the C++ standard those names shouldn't be reserved to the implementation and thus be available.

According to man 3 makedev:

The makedev(), major(), and minor() functions are not specified in POSIX.1, but are present on many other systems

and

These interfaces are defined as macros. Since glibc 2.3.3, they have been aliases for three GNU-specific functions: gnu_dev_makedev(), gnu_dev_major(), and gnu_dev_minor(). The latter names are exported, but the traditional names are more portable.

It seems that they aren't removed for backward compatibility (e.g. https://bugzilla.redhat.com/show_bug.cgi?id=130601).

I think you could #undef them without major issues (many projects proceed in this way).

With G++/CLANG/MSVC you could also do something like:

#pragma push_macro("minor")
#undef minor

// do what you need

#pragma pop_macro("minor")

It's ugly, but helps with naming conflicts.

Moreover, depending on how your code is structured, this trick can be useful:

#define minor(dev) gnu_dev_major(dev)

void (minor)(int row, int col) { /* ... */ }

In the function definition line, the character after 'minor' is a close parenthesis, so it is not a macro invocation.

Marquettamarquette answered 7/3, 2014 at 14:53 Comment(1)
Thanks for the pointer to the Redhat bug. I have filed a bug with gcc since the -std=c++11 should have not pulled in these macros. Jonathan Wakely marked my filing as a dupe of gcc.gnu.org/bugzilla/show_bug.cgi?id=51749 with the note that fixing this problem is general was on his list after the 4.9 release.Fatalism

© 2022 - 2024 — McMap. All rights reserved.