Подтвердить что ты не робот

C4127: условное выражение постоянное

Следующий код генерирует предупреждение C4127 (условное выражение постоянное) в Visual Studio 2010 (где alias_wchar_t является псевдонимом для wchar_t):

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

Какой самый элегантный способ решить эту проблему, если не подавить предупреждение?

Лучшее решение, с которым я столкнулся, состоит в том, чтобы наложить условное выражение на статический bool и использовать это как условие. Там очень много кода выше и ниже if-else, поэтому я переношу все это в фигурные скобки, чтобы максимально ограничить область действия переменной:

// <snip>

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

// <snip>

Это выглядит довольно грубо. Кажется, что он должен быть разрешен во время компиляции, а не во время выполнения, но препроцессор не знает о sizeof. Есть ли более чистый, более элегантный способ решить эту проблему?

4b9b3361

Ответ 1

Похоже, вы знаете, что происходит, и с вами все в порядке.

Компилятор pragma предназначен для таких случаев:

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

По сути, вы сообщаете компилятору (и, что еще важнее, читателям вашего кода), что вы просмотрели предупреждение и знаете, что вы делаете.

Ответ 2

Какой самый изящный способ решить эту проблему, за исключением подавления предупреждение?

Условие известно во время компиляции, поэтому вы также можете выполнить проверку во время компиляции. Не используйте 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.

Ответ 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
}

Это не идеально, но кажется более легким, чем другие решения, и многократно используется для разных типов констант.

Ответ 4

Это то, что я придумал. Он не вызывает никаких предупреждений в Microsoft Visual Studio 2013 и не требует, чтобы вы использовали специальные типы Pragma Visual С++.

Сначала определите следующий класс шаблонов.

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

Я получил идею из С++ 14 std:: conditional, описанной в http://en.cppreference.com/w/cpp/types/conditional.

Ответ 5

Если это просто постоянное выражение, используйте:

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 генерируется простым действием оценки выражения константы в инструкции управления.