summaryrefslogtreecommitdiffstats
path: root/src/common/bit_field.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/bit_field.h')
-rw-r--r--src/common/bit_field.h24
1 files changed, 23 insertions, 1 deletions
diff --git a/src/common/bit_field.h b/src/common/bit_field.h
index dfd00d198..b6f0179c6 100644
--- a/src/common/bit_field.h
+++ b/src/common/bit_field.h
@@ -124,14 +124,35 @@ public:
// so that we can use this within unions
BitField() = default;
+#ifndef _WIN32
+ // We explicitly delete the copy assigment operator here, because the
+ // default copy assignment would copy the full storage value, rather than
+ // just the bits relevant to this particular bit field.
+ // Ideally, we would just implement the copy assignment to copy only the
+ // relevant bits, but this requires compiler support for unrestricted
+ // unions.
+ // MSVC 2013 has no support for this, hence we disable this code on
+ // Windows (so that the default copy assignment operator will be used).
+ // For any C++11 conformant compiler we delete the operator to make sure
+ // we never use this inappropriate operator to begin with.
+ // TODO: Implement this operator properly once all target compilers
+ // support unrestricted unions.
+ BitField& operator=(const BitField&) = delete;
+#endif
+
__forceinline BitField& operator=(T val)
{
- storage = (storage & ~GetMask()) | ((val << position) & GetMask());
+ storage = (storage & ~GetMask()) | (((StorageType)val << position) & GetMask());
return *this;
}
__forceinline operator T() const
{
+ return Value();
+ }
+
+ __forceinline T Value() const
+ {
if (std::numeric_limits<T>::is_signed)
{
std::size_t shift = 8 * sizeof(T)-bits;
@@ -168,5 +189,6 @@ private:
static_assert(position < 8 * sizeof(T), "Invalid position");
static_assert(bits <= 8 * sizeof(T), "Invalid number of bits");
static_assert(bits > 0, "Invalid number of bits");
+ static_assert(std::is_standard_layout<T>::value, "Invalid base type");
};
#pragma pack()