19

以下代码在 Visual Studio 2010 中生成警告 C4127(条件表达式为常量)(其中 alias_wchar_t 是 wchar_t 的别名):

if (sizeof(alias_wchar_t) == sizeof(wchar_t)) // warning occurs here
{
    // do stuff
}
else
{
    // do other stuff
}

除了抑制警告之外,解决此问题的最优雅方法是什么?

我想出的最佳解决方案是将条件填充到静态布尔值中,并将其用作条件。if-else 的上方和下方都有大量代码,所以我将整个代码用大括号括起来,以尽可能地限制变量的范围:

// <snip>

{
    static bool isSameSize = (sizeof(alias_wchar_t) == sizeof(wchar_t));
    if (isSameSize)
    {
        // do stuff
    }
    else
    {
        // do other stuff
    }
}

// <snip>

不过这感觉很恶心。这似乎应该在编译时而不是运行时解决,但预处理器不知道 sizeof。有没有更干净、更优雅的方法来解决这个问题?

4

6 回答 6

8

在 C++17 中,解决方案是使用 if constexpr:

if constexpr (sizeof(alias_wchar_t) == sizeof(wchar_t)) // warning occurs here
{
    // do stuff
}
else
{
    // do other stuff
}

参考:Visual C++ 博客

于 2018-11-01T13:40:56.910 回答
7

除了抑制警告之外,解决此问题的最优雅方法是什么?

该条件在编译时是已知的,因此您也可以在编译时进行检查。不要使用if,只需让编译器插入对正确函数的调用即可。这是一个完整的例子:

#include <iostream>

typedef short alias_wchar_t; // for testing

template<bool Condition>
struct DoStuff
{
};

template<>
struct DoStuff<true>
{
    static void doStuff()
    {
        std::cout << "sizeof(alias_wchar_t) == sizeof(wchar_t)\n"; 
    }
};

template<>
struct DoStuff<false>
{
    static void doStuff()
    {
        std::cout << "sizeof(alias_wchar_t) != sizeof(wchar_t)\n"; 
    }
};

void doStuff()
{
    DoStuff<sizeof(alias_wchar_t) == sizeof(wchar_t)>::doStuff();
}

int main()
{
    doStuff();
}

我想说,这是否真的比你的原始代码更优雅(只为这个编译单元关闭了那个特定的编译器警告)是基于意见的。

无论如何,这在VC 2013 中编译时没有任何警告。/W4

于 2014-08-29T20:10:02.887 回答
7

看起来您知道发生了什么,并且您对此很好。

Compilerpragma适用于以下情况:

__pragma(warning(push))
__pragma(warning(disable:4127))
if (sizeof(alias_wchar_t) == sizeof(wchar_t)) {
__pragma(warning(pop))
}

从本质上讲,您是在告诉编译器(更重要的是,向您的代码的人类读者)您已经查看了警告,并且您知道自己在做什么。

于 2014-08-29T18:24:32.610 回答
4

另一种禁用警告的方法是创建一个虚拟标识函数并将其用于其中一个常量。

// Define this somewhere
template<typename T> const T& identity(const T& t) { return t; }

...

// NB: 'identity' used only to remove "warning C4127"
if (identity(sizeof(alias_wchar_t)) == sizeof(wchar_t))
{
    // do stuff
}
else
{
    // do other stuff
}

这并不完美,但似乎比其他解决方案更轻量级,并且可重复用于不同类型的常量。

于 2016-03-27T23:38:58.293 回答
3

这就是我想出的。它不会在 Microsoft Visual Studio 2013 中引起任何警告,并且不需要您使用 Visual C++ 特定的编译指示。

首先定义以下模板类。

template <bool b>
struct condition
{
    static bool test()
    {
        return true;
    }
};
template <>
struct condition<false>
{
    static bool test()
    {
        return false;
    }
};

然后如下使用它。

if (condition<sizeof(alias_wchar_t) == sizeof(wchar_t)>::test())

我从http://en.cppreference.com/w/cpp/types/conditional中描述的 C++14 std::conditional 中得到了这个想法。

于 2014-08-29T19:15:23.997 回答
1

如果它只是一个常量表达式,那么使用:

typedef wchar_t alias_wchar_t;
bool constExpression = sizeof(alias_wchar_t) == sizeof(wchar_t);
if (constExpression) // potential warning
{
    // do stuff
}
else
{
    // do other stuff
}

看来 c4127 仅由评估控制语句中的常量表达式的动作生成。

于 2016-03-22T05:08:32.847 回答