2014-08-29 54 views
13

下面的代碼生成在Visual Studio 2010(其中alias_wchar_t是wchar_t的別名)警告C4127(條件表達式是常數):C4127:條件表達式是恆定

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

什麼來解決這個最優雅的方式,壓制警告?

我想出的最佳解決方案是將條件填充到靜態布爾中,並將其用作條件。有上面和下面的if-else,所以我換了整個事情的括號來限制變量儘可能的範圍代碼可遇不可求量:

​​

這種感覺相當總值雖然。這看起來應該可以在編譯時而不是運行時解析,但預處理器不知道sizeof。有沒有更清潔,更優雅的方式來解決這個問題?

+1

note:C++ 17正在考慮類似'如果constexpr'來解決這個問題 – 2016-03-22 05:12:27

回答

5

它看起來像你知道發生了什麼,你很好。

編譯pragma s的意思案件那樣:

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

從本質上講,你是在告訴編譯器(甚至更重要的是,你的代碼的人閱讀器),您已經回顧了警告,並你知道你在做什麼。

+4

我個人認爲Christopher Berman的原始解決方案更好。 Pragma是編譯器特有的,過於冗長。 – 2014-08-29 18:32:33

2

這就是我想到的。它不會在Microsoft Visual Studio 2013中引起任何警告,並且不要求您使用Visual C++特定的Pragma。

首先定義下面的模板類。

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

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

難道你不認爲你已經將代碼量增加了一倍以上嗎?) – 2016-12-15 09:47:37

+0

@AlexanderEnaldiev:代碼長度並不是決定事情維持容易程度的唯一因素。正如我在兩年多前所說的那樣,它是否更優雅取決於代碼的實際情況。 – 2016-12-15 12:31:45

+0

不能同意你的看法。這可能毫無意義。比方說, 模板<布爾StrictCheck> 結構美孚 { 布爾檢查(){ 布爾 RETVAL = checkImpl(); if(Strict) retval = retval && checkStrict(); return retval; } }; 我在這裏有什麼C4127?你不覺得,我很確定這個常量取決於模板參數嗎?或者C4127有什麼意義。它顯示了什麼? 仍然無法弄清楚。無論多少年過去了;) – 2016-12-16 20:47:42

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){} – 2017-06-20 06:00:18

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 
} 

這並不完美,但似乎比其他解決方案更輕量級,並且對於不同類型的常量可重複使用。