转至  http://blog.csdn.net/rnamatrix/article/details/5765462

今天在使用limits中的numeric_limits类模板函数max和min时,编译出现了一个错误:

[c-sharp] view plaincopyprint?
  1. error C2589: '(' : illegal token on right side of '::'
error C2589: '(' : illegal token on right side of '::' 
百思不得其解,后来突然想到max和min很有可能已经被定义成了宏,于是查看包进来的头文件,发现蹊跷肯定在<windows.h>中:
windows.h包括了windef.h头文件,在windef.h中定义有宏:
[c-sharp] view plaincopyprint?
  1. #ifndef NOMINMAX
  2. #ifndef max
  3. #define max(a,b) (((a) > (b)) ? (a) : (b))
  4. #endif
  5. #ifndef min
  6. #define min(a,b) (((a) < (b)) ? (a) : (b))
  7. #endif
  8. #endif /* NOMINMAX */
#ifndef NOMINMAX
#ifndef max
#define max(a,b)            (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b)            (((a) < (b)) ? (a) : (b))
#endif
#endif  /* NOMINMAX */ 
所以这里的max和min的宏定义就与标准模板库中的numeric_limits<*>::max/min的定义发生了冲突,加入#define NOMINMAX问题就解决了。
(注意宏的作用域都是全局(scope-less evil)的)
进一步去google了一下关于类似的max/min宏的定义还发生在哪些常用的头文件中。
这里指出,max/min的宏定义还出现在了stdlib.h和minmax.h头文件中。
在stdlib.h中:
[c-sharp] view plaincopyprint?
  1. #if !__STDC__
  2. #ifndef _POSIX_
  3. /* Non-ANSI names for compatibility */
  4. #ifndef __cplusplus
  5. #define max(a,b) (((a) > (b)) ? (a) : (b))
  6. #define min(a,b) (((a) < (b)) ? (a) : (b))
  7. #endif
  8. ...
#if     !__STDC__
#ifndef _POSIX_
/* Non-ANSI names for compatibility */
#ifndef __cplusplus
#define max(a,b)    (((a) > (b)) ? (a) : (b))
#define min(a,b)    (((a) < (b)) ? (a) : (b))
#endif
... 
一般ANSI C中使用__max和__min宏,max和min只是在非标准C中才会定义,所以一般使用标准C时,包括了stdlib.h头文件不会发生和max/min宏的冲突。
而minmax.h头文件一般只是在你想使用max/min宏时才会被包括进来。
并且,在网上还发现了此问题的另外一个解决方式:
[c-sharp] view plaincopyprint?
  1. (std::min)(x, y);
  2. (std::max)(x, y);
  3. (std::numeric_limits<T>::min)();
  4. (std::numeric_limits<T>::max)();
(std::min)(x, y);
(std::max)(x, y);
(std::numeric_limits<T>::min)();
(std::numeric_limits<T>::max)(); 
这样把函数名用括号括起来了,max/min不再被当作带参数的宏去替换了,因此能够避免冲突。
当用户自己定义的类型的成员函数与全局的宏定义发生冲突时,都可以采用这种解决方法。
[c-sharp] view plaincopyprint?
  1. template <typename T, int Size>
  2. struct Series
  3. {
  4. T min() { return *(std::min_element(s, s + Size); }
  5. T& operator[](int index) { return s[index]; }
  6. private:
  7. T s[Size];
  8. };
  9. Series<int, 3> s;
  10. s[0] = 2;
  11. s[1] = 3;
  12. s[2] = 1;
  13. int m = (s.min)(); // long way, but here is the trick
template <typename T, int Size>
struct Series
{
T min() { return *(std::min_element(s, s + Size); }
T& operator[](int index) { return s[index]; }
private:
T s[Size];
};
Series<int, 3> s;
s[0] = 2;
s[1] = 3;
s[2] = 1;
int m = (s.min)(); // long way, but here is the trick 
只是,这种方式可能会面临一些负面影响:
这种方式下不能使用ADL(Argument Depended Name Lookup)了,所以成员函数前必须加上类名或者名字空间域名,也就是必须是fully qualified。

C++ 标准库函数与宏定义的名字冲突相关推荐

  1. 【C进阶】之宏定义的扩展

    宏定义扩展在底层经常看到 1. 常量宏定义 2. 定义宏函数 3. 宏定义和#号结合 4. 宏定义和两个#结合 5. 宏定义和do...while()的结合 6. #ifdef...#else...# ...

  2. C语言便于调试的宏定义 __FILE__、__FUNCTION__、__LINE__、__VA_ARGS__ 参数使用

    __FILE__.__FUNCTION__.__LINE__ 这几个宏定义从名字就可以看出功能: __FILE__:宏在预编译时会替换成当前的源文件名,字符串类型. __FUNCTION__:宏在预编 ...

  3. 【GCC编译优化系列】宏定义名称与函数同名是一种什么骚操作?

    作者简介 *架构师李肯(全网同名)**,一个专注于嵌入式IoT领域的架构师.有着近10年的嵌入式一线开发经验,深耕IoT领域多年,熟知IoT领域的业务发展,深度掌握IoT领域的相关技术栈,包括但不限于 ...

  4. abs int 宏定义_在标准C中,预处理语句,特别是宏定义中,常常出现'#'和'##'符号,#字符串创建运算符#...

    我看<U   N   I   X环境高级编程>第七章时看到这么条宏定义: #define   doit(name)   pr_limits(#name,   name) 这里第二个#号是什 ...

  5. 【C++】C++标准中定义的名字和标识符

    标识符 identifier C++中标识符有明确的定义,对保留的标识符也有明确的说明. 标识符是任意长的字母/字符,数字,下划线的序列.但是有效标识符必须以非数字起头,且是大小写敏感的,标识符中的每 ...

  6. 国际绝对音名十二等律标准对照音高频率的宏定义(32位无符号整型精度、十二等律体系、A4=440.01000Hz)

    国际绝对音名十二等律标准对照音高频率的宏定义(32位无符号整型精度.十二等律体系.A4=440.01000Hz) 代码如下: #ifndef __PITCH_H__ #define __PITCH_H ...

  7. 【Kernel学习】基础篇——01一些标准宏定义和文件include关系

    先从最简单的宏定义学习学习:熟悉一下内核中的一些基本类型的定义,和代码风格 今天我们从stddef.h文件开始看: 1.include/linux/stddef.h 1 #ifndef _LINUX_ ...

  8. c++fabs函数_C语言中常用的标准库函数有哪些?

    点击上方蓝色字关注我们! 本文转自网络,版权归原作者所有. 标准头文件包括: 一.标准定义() 文件里包含了标准库的一些常用定义,无论我们包含哪个标准头文件,都会被自动包含进来. 这个文件里定义: 类 ...

  9. 6、宏定义与预处理、函数与函数库

    C语言预处理理论 由源码到可执行程序的过程 源码.c->(编译)->elf可执行程序 源码.c->(编译)->目标文件.o->(链接)->elf可执行程序 源码.c ...

最新文章

  1. python输入列表方法_Python用input输入列表的方法
  2. RecycleView 嵌套 RecycleView 导致自动滚动
  3. 模拟video播放器
  4. ITK:过滤图像FilterImage
  5. 让文本输入框只能输入数字
  6. Apache cxf JaxRs基本应用
  7. 【Android 12 AOSP学习】Android 12源码下载编译
  8. android 键盘 横屏 边框,Android横屏时软键盘全屏问题
  9. 数电课设交通灯控制器
  10. 云计算是一种商业模式
  11. are in unnamed module of loader ‘app‘)“ }
  12. 开涛老师对Java的全部理解,很透彻。
  13. 数字转中文(大写,小写)数字,金额
  14. C语言入门(四):有关逻辑的运算符和表达式
  15. 关于图像分割的预处理 transform
  16. c语言实现表白代码,给你现在(未来)的那个她(他)准备一个吧
  17. 上午还在改bug,下午就被离职!年底大裁员寒潮来袭……
  18. 小白mybatis学习(三)输出结果配置
  19. cst是什么时间(Cst是什么检查)
  20. 智能照明控制系统的设计和应用

热门文章

  1. ESET nod32
  2. JS(Javascript)调用Android原生方法三步走
  3. MySQL 数据导入
  4. 用计算机打字教案,《打字机》教案
  5. Winform-全国24小时降水量
  6. 【Git】Git的使用与学习
  7. 技术答疑 普通音效、技能音效与动画音效的区别
  8. C++ list及数组中数字相连输出问题
  9. Java统计数组中各个数字出现的个数和字符串中各个字符出现的个数
  10. 广东省地铁行业发展现状与动态前景评估报告2022版