我可以明确地取消定义特定功能的宏吗?

时间:2015-03-17 10:54:54

标签: c++ windows c-preprocessor

我已经编写了一个模板函数来执行整数的快速日志库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;
} 

3 个答案:

答案 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 是您问题的主要解决方案:它会抑制minmax宏的定义。很可能它仍然需要将修复添加到GDI +标头,这至少最初依赖于Windows minmax。但是由于微软的其他不良做法,你通常需要包装每个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}}已证明不可靠。