D
David O
I am using the CRTP (Curiously Recurring Template Pattern) to provide a
set of low-level functions customizable by environment. Using CRTP
ensures that all the function have the same signatures, which becomes
important as the interfaces grow, especially where hardware interfaces
are involved.
For example:
// Feature set for the environment...
template< class Implementation >
class Interface
{
public: // Define a function and its signature...
static void do_it( int );
};
// Definition for real environment...
class Hardware
: public Interface< Hardware >
{
// Nothing here as everything is in Interface<Hardware>
// so signatures *must* match.
};
// Implementation of real environment...
template<>
void Interface< Hardware >::do_it( int i ) { /* Hack i */ }
// Definition for test harness...
class Simulated
: public Interface<Simulated>
{
public:
// Nothing here as everything is in Interface<Simulated>
// so signatures *must* match.
private:
static int it; // Implementation of test harness.
friend class Interface<Simulated>;
};
// Implementation of test harness...
template<>
void Interface<Simulated>::do_it( int i ) { Simulated::it = i; }
So far, this works fine, but I want to add another level of
templatization. Wheeler's Law applies precisely: "Any problem in
computer science can be solved with another layer of indirection. But
that usually will create another problem."
My intent was to create a logging version of each implementation, to
allow sessions to be recorded for analysis, etc...
template< class Implementation >
class Logged
: public Interface< Logged<Implementation> >
{
public:
// Nothing here as everything is in Interface<Simulated>
// so signatures *must* match.
private:
static void log( const char *s );
};
// Partially specialize to implement logging of arbitrary
implementations.
template< class Implementation >
void Interface< Logged<Implementation> >::do_it( int i )
{
Logged<Implementation>::log("doing it");
Implementation::do_it( i );
}
The final specialization doesn't compile: g++ gives:
error: invalid use of undefined type 'class
Interface<Logged<Implementation> >'
and Comeau gives the clearer (but no more useful):
error: template argument list must match the parameter list
Varying the template declaration syntax mutates the errors but hasn't
helped. There is a simple workaround, defining the functions in the
Logged template itself, but this returns to the original problem -
changes to function signatures are not checked.
Thanks,
David O.
set of low-level functions customizable by environment. Using CRTP
ensures that all the function have the same signatures, which becomes
important as the interfaces grow, especially where hardware interfaces
are involved.
For example:
// Feature set for the environment...
template< class Implementation >
class Interface
{
public: // Define a function and its signature...
static void do_it( int );
};
// Definition for real environment...
class Hardware
: public Interface< Hardware >
{
// Nothing here as everything is in Interface<Hardware>
// so signatures *must* match.
};
// Implementation of real environment...
template<>
void Interface< Hardware >::do_it( int i ) { /* Hack i */ }
// Definition for test harness...
class Simulated
: public Interface<Simulated>
{
public:
// Nothing here as everything is in Interface<Simulated>
// so signatures *must* match.
private:
static int it; // Implementation of test harness.
friend class Interface<Simulated>;
};
// Implementation of test harness...
template<>
void Interface<Simulated>::do_it( int i ) { Simulated::it = i; }
So far, this works fine, but I want to add another level of
templatization. Wheeler's Law applies precisely: "Any problem in
computer science can be solved with another layer of indirection. But
that usually will create another problem."
My intent was to create a logging version of each implementation, to
allow sessions to be recorded for analysis, etc...
template< class Implementation >
class Logged
: public Interface< Logged<Implementation> >
{
public:
// Nothing here as everything is in Interface<Simulated>
// so signatures *must* match.
private:
static void log( const char *s );
};
// Partially specialize to implement logging of arbitrary
implementations.
template< class Implementation >
void Interface< Logged<Implementation> >::do_it( int i )
{
Logged<Implementation>::log("doing it");
Implementation::do_it( i );
}
The final specialization doesn't compile: g++ gives:
error: invalid use of undefined type 'class
Interface<Logged<Implementation> >'
and Comeau gives the clearer (but no more useful):
error: template argument list must match the parameter list
Varying the template declaration syntax mutates the errors but hasn't
helped. There is a simple workaround, defining the functions in the
Logged template itself, but this returns to the original problem -
changes to function signatures are not checked.
Thanks,
David O.