2014-08-29 5 views
13

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

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

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

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

// <snip> 

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

// <snip> 

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

+1

примечание: C++ 17 рассматривает нечто вроде 'if constexpr', которое решило бы эту проблему. –

ответ

5

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

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

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

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

+4

Лично я считаю, что оригинальное решение Кристофера Бермана лучше. Pragmas являются компилятором, специфичным и чрезмерно подробным. –

2

Это то, что я придумал. Он не вызывает никаких предупреждений в 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 станд :: условно описанной в http://en.cppreference.com/w/cpp/types/conditional.

5

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

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

+0

Вам не кажется, что вы только удвоили количество кода для mantain;) –

+0

@AlexanderEnaldiev: Длина кода не является единственным фактором в определении того, как легко что-то можно поддерживать. Как я сказал здесь более двух лет назад, более элегантный или нет, зависит от фактического контекста кода. –

+0

Не могу согласиться с вами. Это может быть бессмысленно. Скажем шаблон структура Foo { BOOL Check() { BOOL RetVal = checkImpl(); if (Strict) retval = retval && checkStrict(); return retval; } }; Для чего у меня C4127? Разве вы не думаете, я уверен, что константа зависит от шаблона arg? Или в чем смысл C4127. Что он показывает? Не могу понять. Независимо от лет прошло;) –

1

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

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

+0

Я использовал вариант этого успеха: constexpr bool constExpression = sizeof (alias_wchar_t) == sizeof (wchar_t); if (constExpression) {} –

+0

Это не сработало для меня, используя компилятор VS2012. Все равно получил такое же предупреждение в выражении «if». –

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 
} 

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

Смежные вопросы