C4127:条件表达式为常量
C4127: Conditional Expression is Constant
以下代码在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。有没有更干净、更优雅的方法来解决这个问题?
除了抑制警告
该条件在编译时是已知的,因此您也可以在编译时进行检查。不要使用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();
}
我认为,这是否真的比原始代码更优雅(只关闭了该编译单元的特定编译器警告)是基于意见的。
在任何情况下,这在/W4
与VC 2013的无警告的情况下编译。
在C++17中,解决方案是使用if constexpr:
if constexpr (sizeof(alias_wchar_t) == sizeof(wchar_t)) // warning occurs here
{
// do stuff
}
else
{
// do other stuff
}
参考:Visual C++博客
看起来你知道发生了什么,对此你很满意。
编译器pragma
适用于以下情况:
__pragma(warning(push))
__pragma(warning(disable:4127))
if (sizeof(alias_wchar_t) == sizeof(wchar_t)) {
__pragma(warning(pop))
}
从本质上讲,您是在告诉编译器(更重要的是,告诉代码的人类读者)您已经查看了警告,并且您知道自己在做什么。
// 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
}
这并不完美,但似乎比其他解决方案更轻,并且可用于不同类型的常量。
这就是我想到的。它不会在Microsoft Visual Studio 2013中引起任何警告,也不要求您使用Visual C++特定的Pragmas。
首先定义以下模板类。
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())
我从C++14 std::conditional中得到了这个想法http://en.cppreference.com/w/cpp/types/conditional.
如果它只是一个常量表达式,则使用:
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似乎只是通过评估控制语句中的常量表达式的操作生成的。
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 当一个值是非常量但用常量表达式初始化时使用constexpr
- 使用自动推导的 lambda 参数作为常量表达式
- 生成提升::hana::set 的常量表达式问题
- 为什么不能用常量表达式声明数组?
- 不是 lambda 函数中的常量表达式
- 函数调用在常量表达式中必须具有常量值
- 错误:constexpr 变量'struct2Var'必须由常量表达式初始化
- 关于在需要常量表达式的上下文中使用的glvalue常量表达式的问题
- 生成 constexpr 字符串表,不能产生常量表达式
- 整体模板参数。错误:在常量表达式中使用'this'
- 如何在满足常量表达式的同时将整数传递给指针,传递给 std::array<double、integer>?
- 编译器错误:函数调用在常量表达式中必须有一个常量值
- 错误:'new'不能出现在常量表达式中
- 我可以写出小于 -0.5 两个 ulps 的常量表达式双精度吗?
- 编译器在传递 const 变量时返回错误:模板参数不是常量表达式
- 为什么我不能在非常量表达式上使用此模板阶乘函数?
- C++ 使用变量而不是常量表达式初始化数组
- 使用函数参数作为常量表达式的一部分 - gcc vs clang
- 片段着色器中的"错误:在 GLSL 1.30 及更高版本中禁止使用非常量表达式索引的采样器数组"