2010-05-25 12 views
2

我正在使用Ogre和NxOgre,它們都有一個Real typedef,它是floatdouble,具體取決於編譯器標誌。這導致我們大多數編譯器警告現在是:當類型可能改變時,如何最好地處理警告c4305?

warning C4305: 'argument' : truncation from 'double' to 'Ogre::Real' 

當以0.1爲例初始化變量時。通常我會使用0.1f,但如果您將編譯器標誌更改爲雙精度,那麼您會得到反向警告。我想這可能是最好的選擇一個並堅持下去,但我想寫一個適用於任何配置的方式,如果可能的話。

一種修復方法是在出現的文件中使用#pragma warning (disable : 4305),我不知道是否還有其他更復雜的問題可以通過不發出此警告來隱藏。我知道我會推送並在頭文件中彈出它們,以便它們不會最終在代碼中傳播。

另一種方法是創建一個基於類似的準確性編譯選項的一些宏:

#if OGRE_DOUBLE_PRECISION 
    #define INIT_REAL(x) (x) 
#else 
    #define INIT_REAL(x) static_cast<float>(x) 
#endif 

這將需要改變所有的變量初始化迄今所做的,但至少這將是未來的證明。

任何偏好或我沒有想到的東西?

+0

'的static_cast (0.1)'? – jalf 2010-05-25 12:34:43

+0

@jalf - 當你初始化默認值的時候,如果你把它們全部放在這個地方,那麼它就有點兒含義 - 這就是爲什麼我想用一個短的宏。我可以鍵入這個或什麼來使它更易讀/少打字? – identitycrisisuk 2010-05-25 12:43:38

+0

你可以定義一個函數而不是宏。 'template inline Ogre :: Real real(T val){return static_cast (val); }' – jalf 2010-05-25 12:59:50

回答

3

簡單的解決辦法是隻需添加一個角色:

static_cast<Ogre::Real>(0.1); 

,或者你可以寫一個函數來爲你做轉換(類似宏,但是避免所有令人討厭的問題,宏攜帶:

template <typename T> 
inline Ogre::Real real(T val) { return static_cast<Ogre::Real>(val); } 

然後,您可以撥打real(0.1)並獲得值爲Ogre::Real

+0

選擇此作爲接受的答案,因爲它會保持雙精度。如果我確定他們不需要雙精度,我可能會將大多數文字定義爲浮點數。 – identitycrisisuk 2010-05-26 08:51:54

1

顯然,如果您使用的類型是平臺特定的,文字也應該如此。當使用TCHAR,CStrings,LPCTSTR等時,會出現相同的問題......只有更糟:char無法轉換爲wchar_t

所以我的偏好肯定會去初始化宏。消除警告是危險的。

你甚至可以指定你的宏追加「浮動」文字標籤​​:

//#define DOUBLEPREC 

#ifndef DOUBLEPREC 
typedef float REAL; 
#define INIT_REAL(r) (r##f) 
#else 
typedef double REAL; 
#define INIT_REAL(r) r 
#endif 

REAL r = INIT_REAL(.1); 
double d = INIT_REAL(.1); 
float f = INIT_REAL(.1); 
+0

偉大的提示與## f,可能正是需要什麼,我不是很精通你額外的東西你可以在#中使用宏。如果您在宏中添加除文字外的其他內容,而不是僅僅投射浮動的東西,那麼這種方法將無法編譯,而您並不想這麼做。 – identitycrisisuk 2010-05-25 12:08:45

+0

任何人想分享爲什麼這是downvoted?我知道宏一般是邪惡的,但這似乎是一個好用法(雖然如果你的數字沒有小數點就會中斷...) – identitycrisisuk 2010-05-25 12:46:10

+0

實際上使用'typedef' iso'REAL'宏會更好。我承認,我忽略了這一點。 – xtofl 2010-05-25 13:22:07

0

至於我,我會堅持的類型之一,而忘記了這個警告。無論如何,雙/單精度對fps的影響最小(在我的項目中它是< 3%)。

另外值得一提的是(據我所知),DirectX和OpenGL是以單精度工作的。

如果你真的想以正確的方式擺脫這個警告,你可以使用#if的東西,但不是你所做的。更好的方法是讓像

#if OGRE_DOUBLE_PRECISION == 1 
    // Note that 
    typedef double Real; 
#else 
    typedef float Real; 
#endif 

你也可以寫使用食人魔代碼::房地產作爲類型(或typedefing它,所以它會很舒服你)。

+0

這個確切的定義已經存在於Ogre中了,它更多的是當你有Ogre :: Real變量時,你如何使用0.1或0.1f來設置它們。 – identitycrisisuk 2010-05-25 12:06:09

1

始終使用浮點文字進行初始化。每個浮點值都有一個double值,它表示完全相同的十進制數(儘管這可能不是浮點數旨在表示的十進制值的最佳雙精度近似值)。

Visual Studio似乎在編譯時即使在調試版本中也執行擴展,儘管結果並不令人鼓舞:將1.1f傳遞給需要雙遍傳遞的函數1.1000000238418579,但傳遞1.1傳遞1.1000000000000001。 (根據這兩個值的觀察窗口。)

(沒有這樣的問題,有一個精確的表示,當然,如1.25f號碼。)

這是否是一個大問題,還是不行,我不能」不用說,但如果你的遊戲運行正常,那麼它已經可以容忍類似的不準確性。

+0

@brone - 我調查了分配給雙打的號碼的價值,得出了類似的結論。我認爲對於圖形來說浮動效果會很好,但我有一種感覺,對於物理學來說,我們可能需要雙倍的移動速度,以很高的幀率移動很小的距離。對於我不知道的初始任務是否會有所不同,我總是可以使用模板函數的想法來編寫我認爲可能需要更高精度的數字。 – identitycrisisuk 2010-05-26 08:02:19

+0

大多數值將是計算結果,因此在雙計算模式下,計算過程中會獲得額外精度的好處。無論如何,如果你需要雙打,你只需使用double類型而不是Ogre :: Real,整個問題就變得無關緊要了...... – 2010-05-26 16:12:25

相關問題