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. Есть ли более чистый и элегантный способ решить эту проблему?

14

Решение

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

составитель pragmas предназначены для таких случаев:

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

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

7

Другие решения

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

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

5

Другой способ отключить предупреждение — создать фиктивную функцию идентификации и использовать ее для одной из констант.

// 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 и не требует использования определенных прагм Visual C ++.

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

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

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

3

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

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

1

В C ++ 17 решение состоит в том, чтобы использовать if constexpr:

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

Ссылка: Блог о Visual C ++

1