Следующий код генерирует предупреждение 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. Есть ли более чистый и элегантный способ решить эту проблему?
Похоже, вы знаете, что происходит, и вы в порядке с этим.
составитель pragma
s предназначены для таких случаев:
__pragma(warning(push))
__pragma(warning(disable:4127))
if (sizeof(alias_wchar_t) == sizeof(wchar_t)) {
__pragma(warning(pop))
}
По сути, вы сообщаете компилятору (и, что еще важнее, читателям вашего кода), что вы просмотрели предупреждение и знаете, что делаете.
Какой самый элегантный способ решить эту проблему, если не считать подавления
предупреждение?
Условие известно во время компиляции, поэтому вы можете выполнить проверку и во время компиляции. Не используйте 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.
Другой способ отключить предупреждение — создать фиктивную функцию идентификации и использовать ее для одной из констант.
// 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
}
Это не идеально, но кажется более легким, чем другие решения, и его можно использовать для различных типов констант.
Это то, что я придумал. Он не вызывает никаких предупреждений в 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.
Если это просто константное выражение, используйте:
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 генерируется простым действием оценки постоянного выражения в управляющем операторе.
В C ++ 17 решение состоит в том, чтобы использовать if constexpr:
if constexpr (sizeof(alias_wchar_t) == sizeof(wchar_t)) // warning occurs here
{
// do stuff
}
else
{
// do other stuff
}
Ссылка: Блог о Visual C ++