The following code generates warning C4127 (conditional expression is constant) in Visual Studio 2010 (where alias_wchar_t is an alias for wchar_t):
if (sizeof(alias_wchar_t) == sizeof(wchar_t)) // warning occurs here
{
// do stuff
}
else
{
// do other stuff
}
What's the most elegant way to resolve this, short of suppressing the warning?
The best solution I've come up with is to stuff the conditional into a static bool, and use that as the condition. There's a goodly amount of code above and below the if-else, so I wrap the whole thing in braces to limit the scope of the variable as much as possible:
// <snip>
{
static bool isSameSize = (sizeof(alias_wchar_t) == sizeof(wchar_t));
if (isSameSize)
{
// do stuff
}
else
{
// do other stuff
}
}
// <snip>
This feels pretty gross though. This seems like it should be resolvable at compile-time rather than runtime, but the preprocessor doesn't know about sizeof. Is there a cleaner, more elegant way to resolve this?
In C++17, the solution is to use if constexpr:
if constexpr (sizeof(alias_wchar_t) == sizeof(wchar_t)) // warning occurs here
{
// do stuff
}
else
{
// do other stuff
}
Reference: Visual C++ Blog
It looks like you know what is going on, and you are fine with this.
Compiler pragma
s are meant for cases like that:
__pragma(warning(push))
__pragma(warning(disable:4127))
if (sizeof(alias_wchar_t) == sizeof(wchar_t)) {
__pragma(warning(pop))
}
Essentially, you are telling the compiler (and even more importantly, to human readers of your code) that you have reviewed the warning, and that you know what you are doing.
What's the most elegant way to resolve this, short of suppressing the warning?
The condition is known at compile time, so you can make the check at compile time, too. Don't use an if
, just let the compiler insert a call to the right function. Here is a complete example:
#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();
}
Whether that's really more elegant than your original code (with just that particular compiler warning turned off for this compilation unit) is opinion-based, I'd say.
In any case, this compiles with no warnings at /W4
with VC 2013.
An other way to disable the warning is to create a dummy identity function and use it on one of the constants.
// 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
}
This is not perfect but seems more lightweight than other solutions and reusable for different type of constants.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With