What to name container "flavors"?

M

Michael Olea

Hiya.

Frequently (as in at least twice now) I find that when I write some sort of
container I want at least two out of three possible versions:

o fixed max size known at compile time
o fixed max size known at run time
o max size is dynamic

The question is how to name the variants consistently. My usual approach is
to give the "generic" name to whichever flavor I write first and then add
modifiers to the other two whenever prodded to build 'em:

template<size_t NStates, typename TState>
class HiddenMarkovModel {...};

and a week later:

template<typename TState>
class RTHiddenMarkovModel { RTHiddenMarkovModel(size_t nStates)...};

and 3 weeks after that:

template<typename TState>
class DynamicHiddenMarkovModel { ... };

OK, truth is I've yet to need to code DynamicHiddenMarkovModel - bad
example. But:

template<typename TCell>
class Stack { Stack(size_t maxStates) ...};

template<size_t NStates, typename TCell>
class FixedStack {...};

template<typename TCell>
class DynamicStack {...};

has come up. Sort of a trivial question, how to name these things to reduce
average client surprise (library name entropy), but I am wondering how
y'all cope with this.

- Michael
 
D

Donovan Rebbechi

Hiya.

Frequently (as in at least twice now) I find that when I write some sort of
container I want at least two out of three possible versions:

o fixed max size known at compile time
o fixed max size known at run time
o max size is dynamic

The question is how to name the variants consistently. My usual approach is
to give the "generic" name to whichever flavor I write first and then add
modifiers to the other two whenever prodded to build 'em:

One way to do it is make it all the same class, and make the dynamic or
staticness a policy parameter.

struct dynamic {} ;

template <size_t i> struct static_fixed {} ;
struct rt_fixed {} ;

template <typename T, typename policy = dynamic> class Array ;

So now your classes would be called things like:

Array<Foo, dynamic> a1; // a dynamic array
Array<Foo, static_fixed<10> > a2; // a fixed array, sze known at compile time
Array<Foo, rt_fixed > a3(30); // a fixed array, size known at runtime

template <typename T>
class Array <T, dynamic > : private std::vector<T>
{
public:
typedef typename std::vector<T>::size_type size_type;
// etc ...

Array() : std::vector<T> () {}
Array(size_type N) : std::vector<T> (N) {}
template <typename iter> Array (iter i1, iter i2)
: std::vector<T>(i1,i2) {}
T& operator [] (size_type i) { return std::vector<T>::eek:perator[] (i); }
const T& operator [] (size_type i)const
{ return std::vector<T>::eek:perator[] (i); }

// blah blah
};

// Array<T, rt_fixed> is the same except some functionality needs to be
// restricted, e.g. resize, push_back, capacity, etc.

template <typename T, size_t i>
class Array<T, static_fixed<i> >
{
T impl;
public:
// blah blah blah ...
};

Cheers,
 
M

Michael Olea

Donovan said:
One way to do it is make it all the same class, and make the dynamic or
staticness a policy parameter.

Yeah. I gave that idea a good, hard, intense 5 minute's thought before
posting. My conclusion was that that is certainly the way to go when
feasible, but it probably only reduces rather than eliminates the problem -
there will still be cases where separate classes have to be written, and
named (I think). An interesting exercise would be to take that approach
with bitsets - have std::bitset and boost::dynamic_bitset fall out as
struct dynamic {} ;

template <size_t i> struct static_fixed {} ;
struct rt_fixed {} ;

template <typename T, typename policy = dynamic> class Array ;

So now your classes would be called things like:

Array<Foo, dynamic> a1; // a dynamic array
Array<Foo, static_fixed<10> > a2; // a fixed array, sze known at compile
time
Array<Foo, rt_fixed > a3(30); // a fixed array, size known at runtime

template <typename T>
class Array <T, dynamic > : private std::vector<T>
{
public:
typedef typename std::vector<T>::size_type size_type;
// etc ...

Array() : std::vector<T> () {}
Array(size_type N) : std::vector<T> (N) {}
template <typename iter> Array (iter i1, iter i2)
: std::vector<T>(i1,i2) {}
T& operator [] (size_type i) { return std::vector<T>::eek:perator[] (i);
} const T& operator [] (size_type i)const
{ return std::vector<T>::eek:perator[] (i); }

// blah blah
};

// Array<T, rt_fixed> is the same except some functionality needs to be
// restricted, e.g. resize, push_back, capacity, etc.

Right. Maybe Array derives publicly from the parameterized Size_Policy,
which, if dynamic, has the enriched interface...
template <typename T, size_t i>
class Array<T, static_fixed<i> >
{
T impl;
public:
// blah blah blah ...
};

Cheers,


Cheers, and thanks for the ideas - Michael
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top