C++ 標準庫函數與宏定義的名字衝突

來源:互聯網
上載者:User

轉至  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。

轉至  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。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.