A technique for compile-time detection of erroneous bit-masks -opinionsrequested

G

Gianni Mariani

Below is an example of how to do static type-checking of an erroneous
set of input masks.

The drawback is that it's a little too verbose and non-trivial to
understand and to make it truly

I'd like to hear if you think this is overboard or you'd like to see
more code like this ?

------------------------------------------------------------------------

#include "at_assert.h" // for static assert

// List of all the attributes and the bit positions
#define AT_WriteAttributeList( A ) \
A( WriteAppend, 0 ) \
A( NoExistCreate, 1 ) \
A( CreateExclusive, 2 ) \
A( Truncate, 3 ) \
A( Sync, 4 ) \
A( DirectIO, 5 ) \

// for defining enum entries
#define AT_AttributeEnumDef( Name, Num ) \
e_ ## Name = 1 << (Num),

// for declaring static member variables
// to use in expressions.
#define AT_StaticVariableDecl( Name, Num ) \
static const AttrTempl< e_ ## Name > Name;

// for defining the member variables
#define AT_StaticVariableDefn( Name, Num ) \
const Attr::AttrTempl< Attr::e_ ## Name > Attr::Name;

// Helper to define illegal combinations
#define AT_IllegalCombo( X, A, B ) \
AT_StaticAssert( \
( X & ( e_ ## A | e_ ## B ) ) != ( e_ ## A | e_ ## B ), \
Cannot_have_ ## A ## _and_ ## B ## _in_the_same_attribute_set \
); \
// end macro //

// ======== Attr ============================================
/**
* Attribute class - represents basic attributes
*
*/

class Attr
{
protected:

public: // Rather not have this private

// ======== Attribute ============================================
/**
* The enums of various attributes.
*
*/

enum Attribute
{
// expands to define a list of enums
AT_WriteAttributeList( AT_AttributeEnumDef )
};

public:

// ======== AttrTempl =======================================
/**
* Template of a bit-mask - each time the operator | will return
* a new version of this.
*/

template <Attribute w_Attr>
class AttrTempl
{
public:

AT_IllegalCombo( w_Attr, Truncate, WriteAppend )
AT_IllegalCombo( w_Attr, Sync, DirectIO )

inline AttrTempl()
{}

inline operator Attr ()
{
return Attr( w_Attr );
}

};

// declare things like:
// static const AttrTempl< e_Name > Name
AT_WriteAttributeList( AT_StaticVariableDecl )

// make the constructor harder to create somthing
// unitended.
explicit Attr(
Attribute i_attr
)
: m_attribute( i_attr )
{
}


/**
* The resulting bitmask
*/
unsigned m_attribute;

};

// define the names (this goes in a .cpp file)
AT_WriteAttributeList( AT_StaticVariableDefn )


// bitwise overload of operator| that it's return type
// reflects the actual value.
template <Attr::Attribute w_AttrLhs, Attr::Attribute w_AttrRhs>
inline Attr::AttrTempl<
operator | (
const Attr::AttrTempl< w_AttrLhs > & i_lhs,
const Attr::AttrTempl< w_AttrRhs > & i_rhs
) {
return Attr::AttrTempl<
static_cast said:
}

// simple attribute definition
Attr i_xattr =
Attr::WriteAppend | Attr::NoExistCreate | Attr::CreateExclusive;


// this one will fail at compile-time
//Attr i_xattr_bad =
// Attr::WriteAppend | Attr::Truncate;


Attr Foo()
{
return
Attr::WriteAppend
| Attr::NoExistCreate
| Attr::CreateExclusive;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top