C++ C4127:条件表达式是常量

C++ C4127:条件表达式是常量,c++,visual-studio-2010,c4127,C++,Visual Studio 2010,C4127,以下代码在Visual Studio 2010(其中alias_wchar_t是wchar_t的别名)中生成警告C4127(条件表达式为常量): 除了压制警告之外,解决这个问题最优雅的方法是什么 我提出的最佳解决方案是将条件填充到静态bool中,并将其用作条件。if-else上下都有大量代码,所以我用大括号将整个代码括起来,以尽可能地限制变量的范围: // <snip> { static bool isSameSize = (sizeof(alias_wchar_t) ==

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

除了压制警告之外,解决这个问题最优雅的方法是什么

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

// <snip>

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

// <snip>
//
{
静态bool isSameSize=(sizeof(别名为wchar\u t)=sizeof(别名为wchar\u t));
如果(isSameSize)
{
//做事
}
其他的
{
//做其他事情
}
}
// 

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

看起来你知道发生了什么,而且你对此很满意

编译器
pragma
s适用于以下情况:

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

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

这就是我想到的。它不会在微软Visual Studio 2013中引起任何警告,它不需要使用VisualC++特定的语法。 首先定义以下模板类

template <bool b>
struct condition
{
    static bool test()
    {
        return true;
    }
};
template <>
struct condition<false>
{
    static bool test()
    {
        return false;
    }
};
模板
结构条件
{
静态布尔测试()
{
返回true;
}
};
模板
结构条件
{
静态布尔测试()
{
返回false;
}
};
然后按如下方式使用它

if (condition<sizeof(alias_wchar_t) == sizeof(wchar_t)>::test())
if(条件::测试())
我是从中描述的C++14 std::conditional中得到这个想法的

解决这个问题最优雅的方法是什么,除了抑制 警告

该条件在编译时已知,因此您也可以在编译时进行检查。不要使用
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();
}
#包括
typedef短别名\u wchar\u t;//用于测试
模板
多斯塔夫结构
{
};
模板
多斯塔夫结构
{
静态空隙度
{

std::cout如果它只是一个常量表达式,则使用:

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似乎仅仅是通过计算控制语句中的常量表达式来生成的。

禁用警告的另一种方法是创建一个伪标识函数,并在其中一个常量上使用它

// 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
}
//在某个地方定义它
模板常量T&identity(常量T&T){return T;}
...
//注意:“标识”仅用于删除“警告C4127”
if(identity(sizeof(alias_wchar_t))==sizeof(wchar_t))
{
//做事
}
其他的
{
//做其他事情
}

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

在C++17中,如果constexpr:

// 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
}
if constexpr (sizeof(alias_wchar_t) == sizeof(wchar_t)) // warning occurs here
{
    // do stuff
}
else
{
    // do other stuff
}

参考资料:

我个人认为克里斯托弗·伯曼(Christopher Berman)的原始解决方案更好。Pragmas是特定于编译器的,而且过于冗长。注意:C++17正在考虑类似于
if constexpr
的东西,这可以解决这个问题。你不认为你刚刚将mantain的代码量增加了一倍吗;)@AlexanderEnaldiev:代码长度不是最重要的决定某些东西维护起来有多容易的唯一因素。正如我两年多前在这里所说的,它是否更优雅取决于代码的实际上下文。我不同意你的观点。它可能毫无意义。比如模板结构Foo{bool Check(){bool retval=checkImpl();if(严格)retval=retval&&checkStrict();return retval;}“我有C4127在这里做什么?你不觉得,常数是依赖于模板的ARG吗?或者C4127的要点是什么?它不能显示出来。不管几年过去了,都不知道。”亚历山大EnEnAldidiv:我没有得到C4217。Visual C++ 2015,<代码> /W4< /代码>(甚至不使用代码> /Walth),也就是说,它可以变得更优雅,我不介意警告。你基本上有两个不同的类
Foo
Foo
,一个测试
true==true
,另一个
true==false
。模板专业化在概念上更清晰。你是对的,我错了,——他们从VS2013中移除它。时间过去了(可以用VS2010轻松地再现),但是现在可以把VS2010看作是一个遗留编译器(比如,关于C++ 0x,C++ +0y特征支持)。我用了一个成功的变体:StutExpRoBooCytoSt==siZeof(Aiasas-WaCalyt)= sisiof(WCARAZT);使用VS2012编译器时,这对我不起作用。仍然在“if”语句上得到相同的警告。