Christopher Berman
Christopher Berman

Reputation: 739

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?

Upvotes: 22

Views: 21399

Answers (6)

Arnaud
Arnaud

Reputation: 3741

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

Upvotes: 11

Rexxar
Rexxar

Reputation: 1946

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.

Upvotes: 4

Laurie Stearn
Laurie Stearn

Reputation: 999

If it's just a constant expression then use:

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
}

It appears the c4127 is generated by the mere action of evaluating a constant expression in the control statement.

Upvotes: 3

Christian Hackl
Christian Hackl

Reputation: 27518

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.

Upvotes: 7

Benilda Key
Benilda Key

Reputation: 3094

This is what I have come up with. It does not cause any warnings in Microsoft Visual Studio 2013 and it does not require that you use Visual C++ specific Pragmas.

First define the following template class.

template <bool b>
struct condition
{
    static bool test()
    {
        return true;
    }
};
template <>
struct condition<false>
{
    static bool test()
    {
        return false;
    }
};

Then use it as follows.

if (condition<sizeof(alias_wchar_t) == sizeof(wchar_t)>::test())

I got the idea from the C++14 std::conditional described at http://en.cppreference.com/w/cpp/types/conditional.

Upvotes: 3

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

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.

Upvotes: 7

Related Questions