Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C4127: Conditional Expression is Constant

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?

like image 234
Christopher Berman Avatar asked Aug 29 '14 18:08

Christopher Berman


4 Answers

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

like image 92
Arnaud Avatar answered Nov 07 '22 22:11

Arnaud


It looks like you know what is going on, and you are fine with this.

Compiler pragmas 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.

like image 32
Sergey Kalinichenko Avatar answered Nov 07 '22 22:11

Sergey Kalinichenko


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.

like image 8
Christian Hackl Avatar answered Nov 07 '22 23:11

Christian Hackl


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.

like image 4
Rexxar Avatar answered Nov 07 '22 21:11

Rexxar