我已经编写了一个模板函数来执行整数的快速日志库2。它适用于我的测试程序但是当我将其粘贴到我的主项目中时,我发现我遇到了windows.h
标题的问题。问题是我使用的是c ++ std::numeric_limits<T>::max()
函数,但是windows.h
包含一个也称为max
的宏,它是一个宏,不能识别名称空间并覆盖我的使用尝试真正的C ++功能。无论如何我除了不包括windows.h
之外还能避免这种情况吗? (这不是一个真正的选择)
这是我的功能:
// Returns x where x = log2(n)
template<typename T>
T log2i(T n)
{
static const T infinite(std::numeric_limits<T>::max());
T x = 0;
if (n == 0)
{
return infinite;
}
if (n > 1)
{
while (n >>= 1)
{
++x;
}
}
return x;
}
答案 0 :(得分:4)
static const T infinite((std::numeric_limits<T>::max)());
将起作用:额外的括号阻止宏扩展。
答案 1 :(得分:3)
windows.h
依赖于许多配置符号。
要正确使用此标头,您需要将其包装起来,以便在任何地方获得相同的定义。
最小包装标题:
#pragma once
#undef STRICT
#define STRICT
#undef NOMINMAX
#define NOMINMAX
#undef UNICODE
#define UNICODE
#undef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
使用g ++和MSVC WIN32_LEAN_AND_MEAN
会将行数减少到大约一半。使用g ++,我们谈论的是减少大约60 000→30 000行,并且使用MSVC减少300 000→150 000行。对于翻译单元减少150 000行是恕我直言,其重要性足以在默认情况下定义该符号。
UNICODE
会导致<windows.h>
等CreateWindow
个宏(以及成千上万个类似的函数名宏)扩展到CreateWindowW
( Unicode wchar_t
变体)而不是CreateWindowA
(ANSI char
兼容性变体),并导致TCHAR
映射到wchar_t
而不是char
。对于运行时库,您可以考虑定义与_UNICODE
对应的 UNICODE
,并在定义_MBCS
时输出错误。
NOMINMAX
是您问题的主要解决方案:它会抑制min
和max
宏的定义。很可能它仍然需要将修复添加到GDI +标头,这至少最初依赖于Windows min
和max
。但是由于微软的其他不良做法,你通常需要包装每个Windows标题。
STRICT
现在默认定义,但定义它并没有什么坏处。它为某些函数提供了C ++兼容的声明,例如: IIRC DialogBox
和朋友。
上面未介绍的主要配置是主要版本宏 _WIN32_WINNT
。还有一些其他版本的宏,反映出Windows API的不同部分已经通过不同的方式单独更新,例如,通过Internet Explorer的更新(!)。几年前尝试通过另一个版本控制方案来统一混乱,当然还有它自己的宏,但是你还要主要定义_WIN32_WINNT
并让其他版本的宏派生出来。
答案 2 :(得分:1)
每当我需要#include
<windows.h>
时,我都会使用
#define byte byte_for_windows_include
#include <windows.h>
#undef byte
#ifdef max
# undef max
#endif
#ifdef min
# undef min
#endif
<windows.h>
还会在全局命名空间中发出byte
的定义,这可能很麻烦。
#define STRICT
也是一个好主意。
#define
NOMINMAX
过去{{1}}已证明不可靠。