由于在这种环境中使用GNU标准库,我正在努力解决c ++ 11符号解析中的模糊问题:
示例:
#include <iostream>
#include <string>
struct version {
unsigned major;
unsigned minor;
unsigned patch;
version(unsigned major, unsigned minor, unsigned patch) :
major(major), minor(minor), patch(patch) { }
friend std::ostream & operator<<(std::ostream & out, version const& v) {
out << v.major << ".";
out << v.minor << ".";
out << v.patch;
return out;
}
};
int main(int argc, char ** argv) {
version v(1, 1, 0);
std::cout << v << std::endl;
return 0;
}
编译错误:
error: member initializer 'gnu_dev_major' does not name a non-static data
member or base class
error: member initializer 'gnu_dev_minor' does not name a non-static data
member or base class
命令:
clang++ -std=c++11 -o test *.cpp
范围解析运算符似乎不适用于成员初始化列表,因此我无法弄清楚如何解决歧义。这个示例在没有c ++ 11标志的情况下编译得很好。
答案 0 :(得分:40)
另一种方法是使用大括号:
version(unsigned major, unsigned minor, unsigned patch) :
major{major}, minor{minor}, patch{patch} { }
然后宏不会干扰,因为它们是类似函数的宏,需要调用括号。
答案 1 :(得分:19)
从我自己的编译尝试来看,看起来glibc正在做一些愚蠢的事情和#define
常见的小写字。
当我在#include
之后添加以下内容时,它会编译。
#undef major
#undef minor
答案 2 :(得分:15)
看起来major
和minor
是sys/sysmacros.h
中定义的宏,<iostream>
引入了这些宏,因为这些名称are not reserved for the implementation存在问题。请注意,如果代码减少并且我们直接包含sys/sysmacros.h
,则会出现同样的问题。
当我使用clang on Wandbox编译时,我得到了这个更具信息性的错误,这使我们能够看到冲突的来源:
usr/include/x86_64-linux-gnu/sys/sysmacros.h:67:21: note: expanded from macro 'major'
# define major(dev) gnu_dev_major (dev)
^~~~~~~~~~~~~~~~~~~
usr/include/x86_64-linux-gnu/sys/sysmacros.h:68:21: note: expanded from macro 'minor'
# define minor(dev) gnu_dev_minor (dev)
^~~~~~~~~~~~~~~~~~~
我们可以在以下错误报告identifier major macro expanded into gnu_dev_major中找到:
问题是g ++添加-D_GNU_SOURCE和major()是一个宏 在_GNU_SOURCE(或_BSD_SOURCE或未请求任何功能集时)。
在包含标题后,您总是可以#undef major。
和
makedev(),major()和minor()应该是函数,而不是宏。
看起来它们是在sys / sysmacros.h中的 GNUC &gt; = 2中引入的 向后兼容性。 这不是一个好主意。
摆弄宏是危险的,因为它会污染用户名空间。
所以我们可以看到undef
宏是一个解决方案,不幸的是推荐的解决方案,因为这是一个不容错误的修复错误:
没有变化。如果某些代码不喜欢宏,请添加 #undefs在适当的#include之后。宏是其中的一部分 API并删除它们只会导致问题。
我们可以在成员初始化程序中使用{}
,但这需要更改参数的类型,因为将它们保留为 int 将是一个不允许的缩小转换。当然,更改名称也是一种可能的解决方案。
更新
我提交了glibc bug report。关于这是真的是一个gcc还是一个glibc bug,有一些问题,细节是相关的。
答案 3 :(得分:9)
/usr/include/sys/sysmacros.h定义了以下宏:
# define major(dev) gnu_dev_major (dev)
# define minor(dev) gnu_dev_minor (dev)
# define makedev(maj, min) gnu_dev_makedev (maj, min)
看起来你必须取消它们或使用其他名称