2010-05-25 1 views
2

Я использую как Ogre, так и NxOgre, которые имеют Real typedef, который либо float, либо double в зависимости от флага компилятора. Это привело к тому, что большинство наших предупреждений компилятора теперь составляют:Как лучше справляться с предупреждением 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

+0

@jalf - немного глоток, если у вас их все по месту, когда вы инициализируете значения по умолчанию - вот почему я подумал об использовании короткого макроса. Могу ли я напечатать это или что-то, чтобы сделать его более читаемым/менее типичным? – identitycrisisuk

+0

вы можете определить функцию вместо макроса. Как насчет 'template inline Ogre :: Real real (T val) {return static_cast (val); } ' – jalf

ответ

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

Выбрал это как принятый ответ, так как он сохранил бы двойную точность. Я, вероятно, определю большинство литералов как float, хотя, если я уверен, что им не нужна двойная точность. – identitycrisisuk

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

+0

Кто-нибудь хочет поделиться, почему это было приостановлено? Я знаю, что макросы, как правило, злые, но это выглядело как обычное использование (хотя оно сломалось бы, если бы у вас не было десятичной точки в вашем номере ...) – identitycrisisuk

+0

Фактически использование 'typedef' iso 'REAL' было бы лучше , Я признаю, я это не замечал. – xtofl

0

Что касается меня, то я бы придерживаться одного из типов и забыть об этом предупреждении. Во всяком случае, двойная/одинарная точность оказывает минимальное влияние на fps (в моих проектах это было < 3%).

Также, как я знаю, DirectX и OpenGL работают с единой точностью.

Если вы действительно хотите избавиться от этого предупреждения надлежащим образом, вы можете использовать материал #if, но не так, как вы. Лучший подход, чтобы сделать что-то вроде

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

Вы также можете написать свой код, используя Ogre :: Real как тип (или typedefing его так, что это будет удобно для вас).

+0

Это точное определение существует в Ogre уже, это больше вопрос о том, когда у вас есть Ogre :: Real variables, как вы их устанавливаете с использованием 0,1 или 0,1f. – identitycrisisuk

1

Всегда инициализировать, используя литералы с плавающей запятой. Каждое значение с плавающей запятой имеет двойное значение, которое представляет собой то же самое десятичное число (хотя это может быть не наилучшее приближение двойной точности к десятичному значению, которое должен представлять float).

Visual Studio, кажется, выполняет расширение во время компиляции даже в отладочных сборках, хотя результаты не совсем вдохновляют: передача 1.1f в функцию, которая принимает двойной проход 1.1000000238418579, но пропускает 1.1 в проходах 1.1000000000000001. (Оба эти значения не в соответствии с окном просмотра.)

(нет таких проблем с числами, которые имеют точное представление, конечно, например, 1.25f.)

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

+0

@brone - Я исследовал значение чисел, присвоенных удвоениям, также пришел к аналогичному выводу. Я думаю, что для графического материала float будет хорошо, но у меня есть ощущение, что для физики нам может понадобиться двойная для перемещения очень малых расстояний с высокой частотой кадров. Независимо от того, что будет иметь значение для первоначальных назначений, я не знаю, я всегда могу использовать идею функции шаблона для чисел, которые, по моему мнению, могут потребовать большей точности. – identitycrisisuk

+0

Большинство значений будут результатом вычислений и в двойном режиме, следовательно, будут иметь преимущество дополнительной точности во время вычислений. В любом случае, если вы НЕОБХОДИМО удваиваете, вы просто используете двойной тип, а не Ogre :: Real, и вся проблема становится неактуальной ... – 2010-05-26 16:12:25

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