bitunion.hh revision 12454
14680Sgblack@eecs.umich.edu/* 25442Sgblack@eecs.umich.edu * Copyright (c) 2007-2008 The Regents of The University of Michigan 34680Sgblack@eecs.umich.edu * All rights reserved. 44680Sgblack@eecs.umich.edu * 54680Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 64680Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 74680Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 84680Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 94680Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 104680Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 114680Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 124680Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 134680Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 144680Sgblack@eecs.umich.edu * this software without specific prior written permission. 154680Sgblack@eecs.umich.edu * 164680Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174680Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184680Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194680Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204680Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214680Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224680Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234680Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244680Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254680Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264680Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274680Sgblack@eecs.umich.edu * 284680Sgblack@eecs.umich.edu * Authors: Gabe Black 294680Sgblack@eecs.umich.edu */ 304680Sgblack@eecs.umich.edu 314680Sgblack@eecs.umich.edu#ifndef __BASE_BITUNION_HH__ 324680Sgblack@eecs.umich.edu#define __BASE_BITUNION_HH__ 334680Sgblack@eecs.umich.edu 3412450Sgabeblack@google.com#include <iostream> 3512450Sgabeblack@google.com#include <type_traits> 3612450Sgabeblack@google.com 374680Sgblack@eecs.umich.edu#include "base/bitfield.hh" 384680Sgblack@eecs.umich.edu 395543Ssaidi@eecs.umich.edu// The following implements the BitUnion system of defining bitfields 404680Sgblack@eecs.umich.edu//on top of an underlying class. This is done through the pervasive use of 414680Sgblack@eecs.umich.edu//both named and unnamed unions which all contain the same actual storage. 424680Sgblack@eecs.umich.edu//Since they're unioned with each other, all of these storage locations 434680Sgblack@eecs.umich.edu//overlap. This allows all of the bitfields to manipulate the same data 444680Sgblack@eecs.umich.edu//without having to have access to each other. More details are provided with 454680Sgblack@eecs.umich.edu//the individual components. 464680Sgblack@eecs.umich.edu 4712450Sgabeblack@google.com//This class wraps around another which defines getter/setter functions which 4812450Sgabeblack@google.com//manipulate the underlying data. The type of the underlying data and the type 4912450Sgabeblack@google.com//of the bitfield itself are inferred from the argument types of the setter 5012450Sgabeblack@google.com//function. 5112450Sgabeblack@google.comtemplate<class Base> 5212450Sgabeblack@google.comclass BitfieldTypeImpl : public Base 5312450Sgabeblack@google.com{ 5412450Sgabeblack@google.com static_assert(std::is_empty<Base>::value, 5512450Sgabeblack@google.com "Bitfield base class must be empty."); 5612450Sgabeblack@google.com 5712450Sgabeblack@google.com private: 5812450Sgabeblack@google.com using Base::setter; 5912450Sgabeblack@google.com 6012450Sgabeblack@google.com template<typename T> 6112450Sgabeblack@google.com struct TypeDeducer; 6212450Sgabeblack@google.com 6312450Sgabeblack@google.com template<typename T> 6412450Sgabeblack@google.com friend class TypeDeducer; 6512450Sgabeblack@google.com 6612450Sgabeblack@google.com template<typename Type1, typename Type2> 6712450Sgabeblack@google.com struct TypeDeducer<void (Base::*)(Type1 &, Type2)> 6812450Sgabeblack@google.com { 6912450Sgabeblack@google.com typedef Type1 Storage; 7012450Sgabeblack@google.com typedef Type2 Type; 7112450Sgabeblack@google.com }; 7212450Sgabeblack@google.com 7312450Sgabeblack@google.com protected: 7412450Sgabeblack@google.com typedef typename TypeDeducer< 7512450Sgabeblack@google.com decltype(&BitfieldTypeImpl<Base>::setter)>::Storage Storage; 7612450Sgabeblack@google.com typedef typename TypeDeducer< 7712450Sgabeblack@google.com decltype(&BitfieldTypeImpl<Base>::setter)>::Type Type; 7812450Sgabeblack@google.com 7912450Sgabeblack@google.com Type getter(const Storage &storage) const = delete; 8012450Sgabeblack@google.com void setter(Storage &storage, Type val) = delete; 8112450Sgabeblack@google.com 8212450Sgabeblack@google.com Storage __storage; 8312450Sgabeblack@google.com 8412450Sgabeblack@google.com operator Type () const 8512450Sgabeblack@google.com { 8612450Sgabeblack@google.com return Base::getter(__storage); 8712450Sgabeblack@google.com } 8812450Sgabeblack@google.com 8912450Sgabeblack@google.com Type 9012450Sgabeblack@google.com operator=(const Type val) 9112450Sgabeblack@google.com { 9212450Sgabeblack@google.com Base::setter(__storage, val); 9312450Sgabeblack@google.com return val; 9412450Sgabeblack@google.com } 9512450Sgabeblack@google.com 9612450Sgabeblack@google.com Type 9712450Sgabeblack@google.com operator=(BitfieldTypeImpl<Base> const & other) 9812450Sgabeblack@google.com { 9912450Sgabeblack@google.com return *this = (Type)other; 10012450Sgabeblack@google.com } 10112450Sgabeblack@google.com}; 10212450Sgabeblack@google.com 10312450Sgabeblack@google.com//A wrapper for the above class which allows setting and getting. 10412450Sgabeblack@google.comtemplate<class Base> 10512450Sgabeblack@google.comclass BitfieldType : public BitfieldTypeImpl<Base> 10612450Sgabeblack@google.com{ 10712450Sgabeblack@google.com protected: 10812450Sgabeblack@google.com using Impl = BitfieldTypeImpl<Base>; 10912450Sgabeblack@google.com using typename Impl::Type; 11012450Sgabeblack@google.com 11112450Sgabeblack@google.com public: 11212450Sgabeblack@google.com operator Type () const { return Impl::operator Type(); } 11312450Sgabeblack@google.com Type operator=(const Type val) { return Impl::operator=(val); } 11412450Sgabeblack@google.com Type 11512450Sgabeblack@google.com operator=(BitfieldType<Base> const & other) 11612450Sgabeblack@google.com { 11712450Sgabeblack@google.com return Impl::operator=(other); 11812450Sgabeblack@google.com } 11912450Sgabeblack@google.com}; 12012450Sgabeblack@google.com 12112450Sgabeblack@google.com//A wrapper which only supports getting. 12212450Sgabeblack@google.comtemplate<class Base> 12312450Sgabeblack@google.comclass BitfieldROType : public BitfieldTypeImpl<Base> 12412450Sgabeblack@google.com{ 12512450Sgabeblack@google.com public: 12612450Sgabeblack@google.com using Impl = BitfieldTypeImpl<Base>; 12712450Sgabeblack@google.com using typename Impl::Type; 12812450Sgabeblack@google.com 12912450Sgabeblack@google.com Type operator=(BitfieldROType<Base> const &other) = delete; 13012450Sgabeblack@google.com operator Type () const { return Impl::operator Type(); } 13112450Sgabeblack@google.com}; 13212450Sgabeblack@google.com 13312450Sgabeblack@google.com//A wrapper which only supports setting. 13412450Sgabeblack@google.comtemplate <class Base> 13512450Sgabeblack@google.comclass BitfieldWOType : public BitfieldTypeImpl<Base> 13612450Sgabeblack@google.com{ 13712450Sgabeblack@google.com protected: 13812450Sgabeblack@google.com using Impl = BitfieldTypeImpl<Base>; 13912450Sgabeblack@google.com using typename Impl::Type; 14012450Sgabeblack@google.com 14112450Sgabeblack@google.com public: 14212450Sgabeblack@google.com Type operator=(const Type val) { return Impl::operator=(val); } 14312450Sgabeblack@google.com Type 14412450Sgabeblack@google.com operator=(BitfieldWOType<Base> const & other) 14512450Sgabeblack@google.com { 14612450Sgabeblack@google.com return Impl::operator=(other); 14712450Sgabeblack@google.com } 14812450Sgabeblack@google.com}; 14912450Sgabeblack@google.com 1504680Sgblack@eecs.umich.edu//This namespace is for classes which implement the backend of the BitUnion 15112450Sgabeblack@google.com//stuff. Don't use any of these directly. 1524680Sgblack@eecs.umich.edunamespace BitfieldBackend 1534680Sgblack@eecs.umich.edu{ 15412450Sgabeblack@google.com template<class Storage, int first, int last> 15512450Sgabeblack@google.com class Unsigned 1564680Sgblack@eecs.umich.edu { 15712450Sgabeblack@google.com static_assert(first >= last, 15812450Sgabeblack@google.com "Bitfield ranges must be specified as <msb, lsb>"); 15912450Sgabeblack@google.com 1604680Sgblack@eecs.umich.edu protected: 16112450Sgabeblack@google.com uint64_t 16212450Sgabeblack@google.com getter(const Storage &storage) const 1634680Sgblack@eecs.umich.edu { 16412450Sgabeblack@google.com return bits(storage, first, last); 1654680Sgblack@eecs.umich.edu } 1664680Sgblack@eecs.umich.edu 16712450Sgabeblack@google.com void 16812450Sgabeblack@google.com setter(Storage &storage, uint64_t val) 1694680Sgblack@eecs.umich.edu { 17012450Sgabeblack@google.com replaceBits(storage, first, last, val); 1714680Sgblack@eecs.umich.edu } 1724680Sgblack@eecs.umich.edu }; 1734680Sgblack@eecs.umich.edu 17412450Sgabeblack@google.com template<class Storage, int first, int last> 17512450Sgabeblack@google.com class Signed 17612450Sgabeblack@google.com { 17712450Sgabeblack@google.com static_assert(first >= last, 17812450Sgabeblack@google.com "Bitfield ranges must be specified as <msb, lsb>"); 17912450Sgabeblack@google.com 18012450Sgabeblack@google.com protected: 18112450Sgabeblack@google.com int64_t 18212450Sgabeblack@google.com getter(const Storage &storage) const 18312450Sgabeblack@google.com { 18412450Sgabeblack@google.com return sext<first - last + 1>(bits(storage, first, last)); 18512450Sgabeblack@google.com } 18612450Sgabeblack@google.com 18712450Sgabeblack@google.com void 18812450Sgabeblack@google.com setter(Storage &storage, int64_t val) 18912450Sgabeblack@google.com { 19012450Sgabeblack@google.com replaceBits(storage, first, last, val); 19112450Sgabeblack@google.com } 19212450Sgabeblack@google.com }; 19312450Sgabeblack@google.com 19412450Sgabeblack@google.com //This class contains the basic bitfield types which are automatically 19512450Sgabeblack@google.com //available within a BitUnion. They inherit their Storage type from the 19612450Sgabeblack@google.com //containing BitUnion. 19712450Sgabeblack@google.com template<class Storage> 19812450Sgabeblack@google.com class BitfieldTypes 1994680Sgblack@eecs.umich.edu { 2004680Sgblack@eecs.umich.edu protected: 20112450Sgabeblack@google.com 2024680Sgblack@eecs.umich.edu template<int first, int last=first> 20312450Sgabeblack@google.com using Bitfield = BitfieldType<Unsigned<Storage, first, last> >; 20412450Sgabeblack@google.com template<int first, int last=first> 20512450Sgabeblack@google.com using BitfieldRO = 20612450Sgabeblack@google.com BitfieldROType<Unsigned<Storage, first, last> >; 20712450Sgabeblack@google.com template<int first, int last=first> 20812450Sgabeblack@google.com using BitfieldWO = 20912450Sgabeblack@google.com BitfieldWOType<Unsigned<Storage, first, last> >; 21010289SAndreas.Sandberg@ARM.com 2114680Sgblack@eecs.umich.edu template<int first, int last=first> 21212450Sgabeblack@google.com using SignedBitfield = 21312450Sgabeblack@google.com BitfieldType<Signed<Storage, first, last> >; 2144680Sgblack@eecs.umich.edu template<int first, int last=first> 21512450Sgabeblack@google.com using SignedBitfieldRO = 21612450Sgabeblack@google.com BitfieldROType<Signed<Storage, first, last> >; 21712450Sgabeblack@google.com template<int first, int last=first> 21812450Sgabeblack@google.com using SignedBitfieldWO = 21912450Sgabeblack@google.com BitfieldWOType<Signed<Storage, first, last> >; 2204680Sgblack@eecs.umich.edu }; 2214680Sgblack@eecs.umich.edu 2224680Sgblack@eecs.umich.edu //When a BitUnion is set up, an underlying class is created which holds 2234680Sgblack@eecs.umich.edu //the actual union. This class then inherits from it, and provids the 2244680Sgblack@eecs.umich.edu //implementations for various operators. Setting things up this way 2254680Sgblack@eecs.umich.edu //prevents having to redefine these functions in every different BitUnion 2264680Sgblack@eecs.umich.edu //type. More operators could be implemented in the future, as the need 2274680Sgblack@eecs.umich.edu //arises. 22812450Sgabeblack@google.com template <class Base> 2294680Sgblack@eecs.umich.edu class BitUnionOperators : public Base 2304680Sgblack@eecs.umich.edu { 23112450Sgabeblack@google.com static_assert(sizeof(Base) == sizeof(typename Base::__StorageType), 23212450Sgabeblack@google.com "BitUnion larger than its storage type."); 23312450Sgabeblack@google.com 2344680Sgblack@eecs.umich.edu public: 23512450Sgabeblack@google.com BitUnionOperators(typename Base::__StorageType const &val) 2364681Sgblack@eecs.umich.edu { 23712450Sgabeblack@google.com Base::__storage = val; 2384681Sgblack@eecs.umich.edu } 2394681Sgblack@eecs.umich.edu 2404681Sgblack@eecs.umich.edu BitUnionOperators() {} 2414681Sgblack@eecs.umich.edu 24212450Sgabeblack@google.com operator const typename Base::__StorageType () const 2434680Sgblack@eecs.umich.edu { 24412450Sgabeblack@google.com return Base::__storage; 2454680Sgblack@eecs.umich.edu } 2464680Sgblack@eecs.umich.edu 24712450Sgabeblack@google.com typename Base::__StorageType 24812450Sgabeblack@google.com operator=(typename Base::__StorageType const &val) 2494680Sgblack@eecs.umich.edu { 25012450Sgabeblack@google.com Base::__storage = val; 25112450Sgabeblack@google.com return val; 2524680Sgblack@eecs.umich.edu } 2534680Sgblack@eecs.umich.edu 25412450Sgabeblack@google.com typename Base::__StorageType 25512450Sgabeblack@google.com operator=(BitUnionOperators const &other) 25610640Sgabeblack@google.com { 25712450Sgabeblack@google.com Base::__storage = other; 25812450Sgabeblack@google.com return Base::__storage; 25910640Sgabeblack@google.com } 26010640Sgabeblack@google.com 2614680Sgblack@eecs.umich.edu bool 26212450Sgabeblack@google.com operator<(Base const &base) const 2634680Sgblack@eecs.umich.edu { 26412450Sgabeblack@google.com return Base::__storage < base.__storage; 2654680Sgblack@eecs.umich.edu } 2664680Sgblack@eecs.umich.edu 2674680Sgblack@eecs.umich.edu bool 26812450Sgabeblack@google.com operator==(Base const &base) const 2694680Sgblack@eecs.umich.edu { 27012450Sgabeblack@google.com return Base::__storage == base.__storage; 2714680Sgblack@eecs.umich.edu } 2724680Sgblack@eecs.umich.edu }; 2734680Sgblack@eecs.umich.edu} 2744680Sgblack@eecs.umich.edu 2754680Sgblack@eecs.umich.edu//This macro is a backend for other macros that specialize it slightly. 2764680Sgblack@eecs.umich.edu//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and 2774680Sgblack@eecs.umich.edu//sticks the class which has the actual union in it, which 2784680Sgblack@eecs.umich.edu//BitfieldOperators above inherits from. Putting these classes in a special 2794680Sgblack@eecs.umich.edu//namespace ensures that there will be no collisions with other names as long 2804680Sgblack@eecs.umich.edu//as the BitUnion names themselves are all distinct and nothing else uses 2814680Sgblack@eecs.umich.edu//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself 28212450Sgabeblack@google.com//creates a typedef of the "type" parameter called __StorageType. This allows 2834680Sgblack@eecs.umich.edu//the type to propagate outside of the macro itself in a controlled way. 2844680Sgblack@eecs.umich.edu//Finally, the base storage is defined which BitfieldOperators will refer to 2854680Sgblack@eecs.umich.edu//in the operators it defines. This macro is intended to be followed by 2864680Sgblack@eecs.umich.edu//bitfield definitions which will end up inside it's union. As explained 28712450Sgabeblack@google.com//above, these is overlayed the __storage member in its entirety by each of the 2884680Sgblack@eecs.umich.edu//bitfields which are defined in the union, creating shared storage with no 2894680Sgblack@eecs.umich.edu//overhead. 2904680Sgblack@eecs.umich.edu#define __BitUnion(type, name) \ 2915442Sgblack@eecs.umich.edu class BitfieldUnderlyingClasses##name : \ 2924680Sgblack@eecs.umich.edu public BitfieldBackend::BitfieldTypes<type> \ 2934680Sgblack@eecs.umich.edu { \ 29412454Sgabeblack@google.com protected: \ 29512454Sgabeblack@google.com typedef type __StorageType; \ 29612454Sgabeblack@google.com friend BitfieldBackend::BitUnionBaseType< \ 29712454Sgabeblack@google.com BitfieldBackend::BitUnionOperators< \ 29812454Sgabeblack@google.com BitfieldUnderlyingClasses##name> >; \ 29912454Sgabeblack@google.com friend BitfieldBackend::BitUnionBaseType< \ 30012454Sgabeblack@google.com BitfieldUnderlyingClasses##name>; \ 3014680Sgblack@eecs.umich.edu public: \ 3024680Sgblack@eecs.umich.edu union { \ 30312450Sgabeblack@google.com type __storage; 3044680Sgblack@eecs.umich.edu 3054680Sgblack@eecs.umich.edu//This closes off the class and union started by the above macro. It is 3064680Sgblack@eecs.umich.edu//followed by a typedef which makes "name" refer to a BitfieldOperator 3074680Sgblack@eecs.umich.edu//class inheriting from the class and union just defined, which completes 3084680Sgblack@eecs.umich.edu//building up the type for the user. 3094680Sgblack@eecs.umich.edu#define EndBitUnion(name) \ 3104680Sgblack@eecs.umich.edu }; \ 3114680Sgblack@eecs.umich.edu }; \ 3124680Sgblack@eecs.umich.edu typedef BitfieldBackend::BitUnionOperators< \ 3135442Sgblack@eecs.umich.edu BitfieldUnderlyingClasses##name> name; 3144680Sgblack@eecs.umich.edu 3154680Sgblack@eecs.umich.edu//This sets up a bitfield which has other bitfields nested inside of it. The 31612450Sgabeblack@google.com//__storage member functions like the "underlying storage" of the top level 3174680Sgblack@eecs.umich.edu//BitUnion. Like everything else, it overlays with the top level storage, so 3184680Sgblack@eecs.umich.edu//making it a regular bitfield type makes the entire thing function as a 3194680Sgblack@eecs.umich.edu//regular bitfield when referred to by itself. 32012450Sgabeblack@google.com#define __SubBitUnion(name, fieldType, ...) \ 32112450Sgabeblack@google.com class \ 3224680Sgblack@eecs.umich.edu { \ 3234680Sgblack@eecs.umich.edu public: \ 3244680Sgblack@eecs.umich.edu union { \ 32512450Sgabeblack@google.com fieldType<__VA_ARGS__> __storage; 3264680Sgblack@eecs.umich.edu 3274680Sgblack@eecs.umich.edu//This closes off the union created above and gives it a name. Unlike the top 3284680Sgblack@eecs.umich.edu//level BitUnion, we're interested in creating an object instead of a type. 3294680Sgblack@eecs.umich.edu//The operators are defined in the macro itself instead of a class for 3304680Sgblack@eecs.umich.edu//technical reasons. If someone determines a way to move them to one, please 3314680Sgblack@eecs.umich.edu//do so. 3324680Sgblack@eecs.umich.edu#define EndSubBitUnion(name) \ 3334680Sgblack@eecs.umich.edu }; \ 33412450Sgabeblack@google.com inline operator __StorageType () const \ 33512450Sgabeblack@google.com { return __storage; } \ 3364680Sgblack@eecs.umich.edu \ 33712450Sgabeblack@google.com inline __StorageType operator = (const __StorageType & _storage) \ 33812450Sgabeblack@google.com { return __storage = _storage;} \ 3394680Sgblack@eecs.umich.edu } name; 3404680Sgblack@eecs.umich.edu 3414680Sgblack@eecs.umich.edu//Regular bitfields 3424680Sgblack@eecs.umich.edu//These define macros for read/write regular bitfield based subbitfields. 3434680Sgblack@eecs.umich.edu#define SubBitUnion(name, first, last) \ 34412450Sgabeblack@google.com __SubBitUnion(name, Bitfield, first, last) 3454680Sgblack@eecs.umich.edu 3464680Sgblack@eecs.umich.edu//Regular bitfields 3474680Sgblack@eecs.umich.edu//These define macros for read/write regular bitfield based subbitfields. 3484680Sgblack@eecs.umich.edu#define SignedSubBitUnion(name, first, last) \ 34912450Sgabeblack@google.com __SubBitUnion(name, SignedBitfield, first, last) 3504680Sgblack@eecs.umich.edu 3514680Sgblack@eecs.umich.edu//Use this to define an arbitrary type overlayed with bitfields. 3524680Sgblack@eecs.umich.edu#define BitUnion(type, name) __BitUnion(type, name) 3534680Sgblack@eecs.umich.edu 3544680Sgblack@eecs.umich.edu//Use this to define conveniently sized values overlayed with bitfields. 3554680Sgblack@eecs.umich.edu#define BitUnion64(name) __BitUnion(uint64_t, name) 3564680Sgblack@eecs.umich.edu#define BitUnion32(name) __BitUnion(uint32_t, name) 3574680Sgblack@eecs.umich.edu#define BitUnion16(name) __BitUnion(uint16_t, name) 3584680Sgblack@eecs.umich.edu#define BitUnion8(name) __BitUnion(uint8_t, name) 3594680Sgblack@eecs.umich.edu 36012451Sgabeblack@google.com 36112451Sgabeblack@google.com//These templates make it possible to define other templates related to 36212451Sgabeblack@google.com//BitUnions without having to refer to internal typedefs or the BitfieldBackend 36312451Sgabeblack@google.com//namespace. 36412451Sgabeblack@google.com 36512451Sgabeblack@google.com//To build a template specialization which works for all BitUnions, accept a 36612451Sgabeblack@google.com//template argument T, and then use BitUnionType<T> as an argument in the 36712451Sgabeblack@google.com//template. To refer to the basic type the BitUnion wraps, use 36812451Sgabeblack@google.com//BitUnionBaseType<T>. 36912451Sgabeblack@google.com 37012451Sgabeblack@google.com//For example: 37112451Sgabeblack@google.com//template <typename T> 37212451Sgabeblack@google.com//void func(BitUnionType<T> u) { BitUnionBaseType<T> b = u; } 37312451Sgabeblack@google.com 37412451Sgabeblack@google.com//Also, BitUnionBaseType can be used on a BitUnion type directly. 37512451Sgabeblack@google.com 37612451Sgabeblack@google.comtemplate <typename T> 37712451Sgabeblack@google.comusing BitUnionType = BitfieldBackend::BitUnionOperators<T>; 37812451Sgabeblack@google.com 37912451Sgabeblack@google.comnamespace BitfieldBackend 38012451Sgabeblack@google.com{ 38112451Sgabeblack@google.com template<typename T> 38212451Sgabeblack@google.com struct BitUnionBaseType 38312451Sgabeblack@google.com { 38412451Sgabeblack@google.com typedef typename BitUnionType<T>::__StorageType Type; 38512451Sgabeblack@google.com }; 38612451Sgabeblack@google.com 38712451Sgabeblack@google.com template<typename T> 38812451Sgabeblack@google.com struct BitUnionBaseType<BitUnionType<T> > 38912451Sgabeblack@google.com { 39012451Sgabeblack@google.com typedef typename BitUnionType<T>::__StorageType Type; 39112451Sgabeblack@google.com }; 39212451Sgabeblack@google.com} 39312451Sgabeblack@google.com 39412451Sgabeblack@google.comtemplate <typename T> 39512451Sgabeblack@google.comusing BitUnionBaseType = typename BitfieldBackend::BitUnionBaseType<T>::Type; 39612451Sgabeblack@google.com 39712454Sgabeblack@google.com 39812454Sgabeblack@google.com//An STL style hash structure for hashing BitUnions based on their base type. 39912453Sgabeblack@google.comnamespace std 40012453Sgabeblack@google.com{ 40112453Sgabeblack@google.com template <typename T> 40212453Sgabeblack@google.com struct hash; 40312453Sgabeblack@google.com 40412453Sgabeblack@google.com template <typename T> 40512453Sgabeblack@google.com struct hash<BitUnionType<T> > : public hash<BitUnionBaseType<T> > 40612453Sgabeblack@google.com { 40712453Sgabeblack@google.com size_t 40812453Sgabeblack@google.com operator() (const BitUnionType<T> &val) const 40912453Sgabeblack@google.com { 41012453Sgabeblack@google.com return hash<BitUnionBaseType<T> >::operator()(val); 41112453Sgabeblack@google.com } 41212453Sgabeblack@google.com }; 41312453Sgabeblack@google.com} 41412453Sgabeblack@google.com 4154680Sgblack@eecs.umich.edu#endif // __BASE_BITUNION_HH__ 416