float, is well, a C++ floating point.
FFloat32 is a structure that represents a float as well as (via a union) the decomposed bitfields for that float's sign, mantissa and exponent parts.
You should generally never use
FFloat32 except when:
- you're using some API that expects a
FFloat32 (these are very rare) or
- you need to do some kind of low-level bit hackery with a floating point value (also fairly rare these days)
It's not that
FFloat32 is bad, per se, it's just that it doesn't really offer you anything you'd need for general-purpose floating point usage.
It is less common than a plain old
float, which has some minor readability impact (others may not know immediately what it is for at a glance). It also doesn't implicitly convert to
float so you'll be typing
something.FloatValue a lot, which is also not a big deal, but could get tedious.
Finally, its use of unions and bitfields is non-portable, and implementation-defined (see below). This is not your problem, it is Epic's job to make sure the type is structured so that it's usable for all supported implementations, but it's a potential source of bugs if they fail to catch an issue with the implementation of the type when a new compiler version is released or added to the list of supported compilers.
So unless you have a need to play with the individual bits in the floating point representation, you should probably just avoid
FFloat32 (its cousin,
FFloat16, may have slightly more utility as there is no standard 16-bit C++ floating point type).
It used to be common to manipulate floats via integer representations of their components for "speed." Modern computers obviate much of that need for many platforms, and the various type-punning techniques that could be used to do this sort of thing can actually be detrimental to performance or correctness in any event.
It should be telling that a search of Unreal's GitHub repository reveals very few uses of the
FFloat32 type. All of them are in the the definition of
FFloat32 itself or in the definition of
FFloat32 does two things which the C++ standard calls out. It:
- allows you to act as if more than one member of the union is active at one time; you are expected to write to the floating point members and read from one of the integer members (9.5.1, [class.union])
- expects the bitfield allocation within the union to match that of the bit allocation of an IEEE floating point value; however, allocation and alignment of bitfield members within a class type is implementation defined (9.6.1, [class.bit])