diff options
| -rw-r--r-- | src/common/bit_field.h | 24 |
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: | |||
| 124 | // so that we can use this within unions | 124 | // so that we can use this within unions |
| 125 | BitField() = default; | 125 | BitField() = default; |
| 126 | 126 | ||
| 127 | #ifndef _WIN32 | ||
| 128 | // We explicitly delete the copy assigment operator here, because the | ||
| 129 | // default copy assignment would copy the full storage value, rather than | ||
| 130 | // just the bits relevant to this particular bit field. | ||
| 131 | // Ideally, we would just implement the copy assignment to copy only the | ||
| 132 | // relevant bits, but this requires compiler support for unrestricted | ||
| 133 | // unions. | ||
| 134 | // MSVC 2013 has no support for this, hence we disable this code on | ||
| 135 | // Windows (so that the default copy assignment operator will be used). | ||
| 136 | // For any C++11 conformant compiler we delete the operator to make sure | ||
| 137 | // we never use this inappropriate operator to begin with. | ||
| 138 | // TODO: Implement this operator properly once all target compilers | ||
| 139 | // support unrestricted unions. | ||
| 140 | BitField& operator=(const BitField&) = delete; | ||
| 141 | #endif | ||
| 142 | |||
| 127 | __forceinline BitField& operator=(T val) | 143 | __forceinline BitField& operator=(T val) |
| 128 | { | 144 | { |
| 129 | storage = (storage & ~GetMask()) | ((val << position) & GetMask()); | 145 | storage = (storage & ~GetMask()) | (((StorageType)val << position) & GetMask()); |
| 130 | return *this; | 146 | return *this; |
| 131 | } | 147 | } |
| 132 | 148 | ||
| 133 | __forceinline operator T() const | 149 | __forceinline operator T() const |
| 134 | { | 150 | { |
| 151 | return Value(); | ||
| 152 | } | ||
| 153 | |||
| 154 | __forceinline T Value() const | ||
| 155 | { | ||
| 135 | if (std::numeric_limits<T>::is_signed) | 156 | if (std::numeric_limits<T>::is_signed) |
| 136 | { | 157 | { |
| 137 | std::size_t shift = 8 * sizeof(T)-bits; | 158 | std::size_t shift = 8 * sizeof(T)-bits; |
| @@ -168,5 +189,6 @@ private: | |||
| 168 | static_assert(position < 8 * sizeof(T), "Invalid position"); | 189 | static_assert(position < 8 * sizeof(T), "Invalid position"); |
| 169 | static_assert(bits <= 8 * sizeof(T), "Invalid number of bits"); | 190 | static_assert(bits <= 8 * sizeof(T), "Invalid number of bits"); |
| 170 | static_assert(bits > 0, "Invalid number of bits"); | 191 | static_assert(bits > 0, "Invalid number of bits"); |
| 192 | static_assert(std::is_standard_layout<T>::value, "Invalid base type"); | ||
| 171 | }; | 193 | }; |
| 172 | #pragma pack() | 194 | #pragma pack() |