base: Enable specializing templates on BitUnion types.

Previously these relied on reaching into private internal definitions
in the BitUnion types.

Change-Id: Ia6c94de92986b85ec9e5fcb197459d450111fb36
Reviewed-on: https://gem5-review.googlesource.com/7202
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
Gabe Black
2018-01-07 18:38:04 -08:00
parent cd9450c1d9
commit 0d56fdef7a
2 changed files with 68 additions and 0 deletions

View File

@@ -351,4 +351,41 @@ namespace BitfieldBackend
#define BitUnion16(name) __BitUnion(uint16_t, name)
#define BitUnion8(name) __BitUnion(uint8_t, name)
//These templates make it possible to define other templates related to
//BitUnions without having to refer to internal typedefs or the BitfieldBackend
//namespace.
//To build a template specialization which works for all BitUnions, accept a
//template argument T, and then use BitUnionType<T> as an argument in the
//template. To refer to the basic type the BitUnion wraps, use
//BitUnionBaseType<T>.
//For example:
//template <typename T>
//void func(BitUnionType<T> u) { BitUnionBaseType<T> b = u; }
//Also, BitUnionBaseType can be used on a BitUnion type directly.
template <typename T>
using BitUnionType = BitfieldBackend::BitUnionOperators<T>;
namespace BitfieldBackend
{
template<typename T>
struct BitUnionBaseType
{
typedef typename BitUnionType<T>::__StorageType Type;
};
template<typename T>
struct BitUnionBaseType<BitUnionType<T> >
{
typedef typename BitUnionType<T>::__StorageType Type;
};
}
template <typename T>
using BitUnionBaseType = typename BitfieldBackend::BitUnionBaseType<T>::Type;
#endif // __BASE_BITUNION_HH__

View File

@@ -31,6 +31,7 @@
#include <cassert>
#include <iostream>
#include <type_traits>
#include "base/bitunion.hh"
#include "base/cprintf.hh"
@@ -140,6 +141,17 @@ class BitUnionData : public testing::Test {
Split split;
void SetUp() override { sixtyFour = 0; split = 0; }
template <typename T>
uint64_t templatedFunction(T) { return 0; }
template <typename T>
uint64_t
templatedFunction(BitUnionType<T> u)
{
BitUnionBaseType<T> b = u;
return b;
}
};
TEST_F(BitUnionData, NormalBitfield)
@@ -239,3 +251,22 @@ TEST_F(BitUnionData, Custom)
EXPECT_EQ(split, 0xf0f0);
EXPECT_EQ((uint64_t)split.split, 0xff);
}
TEST_F(BitUnionData, Templating)
{
sixtyFour = 0xff;
EXPECT_EQ(templatedFunction(sixtyFour), 0xff);
EXPECT_EQ(templatedFunction((uint64_t)sixtyFour), 0);
BitUnion(uint64_t, Dummy64)
EndBitUnion(Dummy64);
BitUnion(uint32_t, Dummy32)
EndBitUnion(Dummy32);
bool is64;
is64 = std::is_same<BitUnionBaseType<Dummy64>, uint64_t>::value;
EXPECT_TRUE(is64);
is64 = std::is_same<BitUnionBaseType<Dummy32>, uint64_t>::value;
EXPECT_FALSE(is64);
}