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<
// 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;
}
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;
}