2014-08-29 99 views
13

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

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

什么来解决这个最优雅的方式,压制警告?

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

​​

这种感觉相当总值虽然。这看起来应该可以在编译时而不是运行时解析,但预处理器不知道sizeof。有没有更清洁,更优雅的方式来解决这个问题?

+1

note:C++ 17正在考虑类似'如果constexpr'来解决这个问题 – 2016-03-22 05:12:27

回答

5

它看起来像你知道发生了什么,你很好。

编译pragma s的意思案件那样:

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

从本质上讲,你是在告诉编译器(甚至更重要的是,你的代码的人阅读器),您已经回顾了警告,并你知道你在做什么。

+4

我个人认为Christopher Berman的原始解决方案更好。 Pragma是编译器特有的,过于冗长。 – 2014-08-29 18:32:33

2

这就是我想到的。它不会在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()) 

我从C++ 14 std ::条件得到了想法,描述在http://en.cppreference.com/w/cpp/types/conditional

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(); 
} 

这是否真的更优雅比你原来的代码(只有特定的编译器警告关闭此编译单元)是基于观点的,我会说。

在任何情况下,这个编译与没有警告/W4与VC 2013年

+0

难道你不认为你已经将代码量增加了一倍以上吗?) – 2016-12-15 09:47:37

+0

@AlexanderEnaldiev:代码长度并不是决定事情维持容易程度的唯一因素。正如我在两年多前所说的那样,它是否更优雅取决于代码的实际情况。 – 2016-12-15 12:31:45

+0

不能同意你的看法。这可能毫无意义。比方说, 模板<布尔StrictCheck> 结构美孚 { 布尔检查(){ 布尔 RETVAL = checkImpl(); if(Strict) retval = retval && checkStrict(); return retval; } }; 我在这里有什么C4127?你不觉得,我很确定这个常量取决于模板参数吗?或者C4127有什么意义。它显示了什么? 仍然无法弄清楚。无论多少年过去了;) – 2016-12-16 20:47:42

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在控制语句中评估常量表达式的行为。

+0

我用成功的一个变种: constexpr bool constExpression = sizeof(alias_wchar_t)== sizeof(wchar_t); if(constExpression){} – 2017-06-20 06:00:18

3

另一种禁用警告的方法是创建伪身份函数并将其用于其中一个常量。

// 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 
} 

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