Как лучше всего бороться с предупреждением c4305, когда тип может измениться? - PullRequest
2 голосов
/ 25 мая 2010

Я использую как Ogre, так и NxOgre, которые оба имеют Real typedef, равный float или double в зависимости от флага компилятора. Это привело к тому, что большинство предупреждений нашего компилятора теперь:

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

, что потребовало бы изменения всех инициализаций переменных, выполненных до сих пор, но, по крайней мере, это будет подтверждением будущего.

Какие-то предпочтения или что-то, о чем я не думал?

Ответы [ 4 ]

3 голосов
/ 25 мая 2010

Простым решением было бы просто добавить приведение:

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.

1 голос
/ 26 мая 2010

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

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

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

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

1 голос
/ 25 мая 2010

Очевидно, что если тип, который вы используете, зависит от платформы, то и литералы должны быть такими. Те же проблемы возникают при использовании TCHAR, CStrings, LPCTSTR и т. Д ..., только хуже: char не может быть преобразовано в wchar_t.

Так что мои предпочтения определенно будут идти к макросу инициализации. Отрабатывать предупреждения опасно.

Вы даже можете указать свой макрос для добавления литерального тега "float":

//#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 голосов
/ 25 мая 2010

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

Также стоит упомянуть (насколько мне известно), DirectX и OpenGL работают с одинарной точностью.

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

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

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

...