以下代码在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
}
解决这个问题最优雅的方法是什么,而不是抑制警告?
我提出的最佳解决方案是将条件填充到静态bool中,并将其用作条件。在if-else之上和之下都有大量代码,所以我将整个事情用括号括起来尽可能地限制变量的范围:
// <snip>
{
static bool isSameSize = (sizeof(alias_wchar_t) == sizeof(wchar_t));
if (isSameSize)
{
// do stuff
}
else
{
// do other stuff
}
}
// <snip>
但这感觉非常糟糕。这似乎应该在编译时而不是运行时可解析,但预处理器不知道sizeof。是否有更清洁,更优雅的方法来解决这个问题?
答案 0 :(得分:7)
看起来你知道发生了什么,你对此很好。
编译器pragma
适用于以下情况:
__pragma(warning(push))
__pragma(warning(disable:4127))
if (sizeof(alias_wchar_t) == sizeof(wchar_t)) {
__pragma(warning(pop))
}
基本上,你告诉编译器(更重要的是,你的代码的人类读者)你已经查看了警告,并且你知道你在做什么。
答案 1 :(得分:5)
解决这个问题最优雅的方法是什么,而不是抑制 的警告?
条件在编译时已知,因此您也可以在编译时进行检查。不要使用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
编译无警告。
答案 2 :(得分: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
}
这并不完美,但似乎比其他解决方案更轻量级,并且可以重复使用不同类型的常量。
答案 3 :(得分:3)
这就是我想出的。它不会在Microsoft Visual Studio 2013中引起任何警告,也不要求您使用特定于Visual C ++的Pragma。
首先定义以下模板类。
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中得到了这个想法。
答案 4 :(得分:2)
在C ++ 17中,解决方案是使用if constexpr:
if constexpr (sizeof(alias_wchar_t) == sizeof(wchar_t)) // warning occurs here
{
// do stuff
}
else
{
// do other stuff
}
答案 5 :(得分: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是仅通过在控制语句中评估常量表达式而生成的。