Given that the difference between a constant visitor and a mutable visitor is that the methods in a constant visitor are not allowed to modify the visited object.
class Integer_Field;
class Boolean_Field;
class Text_Field;
class Visitor_Constant
{
public:
virtual void visit(const Integer_Field& f) = 0;
virtual void visit(const Boolean_Field& f) = 0;
virtual void visit(const Text_Field& f) = 0;
};
class Visitor_Mutable
{
public:
virtual void visit(Integer_Field& f) = 0;
virtual void visit(Boolean_Field& f) = 0;
virtual void visit(Text_Field& f) = 0;
};
I would like to minimize support for these visitors. For example, if I come up with a class Blob_Field, I need to modify both classes. I would prefer to have something where I only have to modify one class or stencil.
The maintenance issue fans out when there are many classes defined from these parent visitors. This is the main reason I want to simplify the maintenance.
My questions:
(Note: This must be resolved without using C++11 features as my development environment does not support C++11 and I'm not allowed to upgrade at this time.)
Is there a way to use the template mechanism to merge the two
(such as supply 'const' as a parameter to the template)?
How can I set up these visitors so that I can pass a
Visitor_Constant to methods using a Visitor_Mutable?
Note: Combining these classes via a parent class, doubles the visitor methods that must be implemented and maintained.
Edit 1: Class relationships
class Component; // Base class for fields and records.
class Field : public Component; // Base class for all fields
class Record : public Component // Base class for all records
{
std::vector< boost::shared_ptr<Component> > component_container;
};
class Integer_Field : public Field;
class Boolean_Field : public Field;
class Text_Field : public Field;
Edit 2: Rationality of fields
One rationality for the fields being treated specifically is the case of generating an SQL statement for creating a table.
Another is for loading fields from a database table.
Is there a way to use the template mechanism to merge the two (such as supply 'const' as a parameter to the template)?
You can supply it through a template template parameter, and also keep the pure visitor implementation generic. I originally did this in C++11, but since you say you don't have it, I'll present one with type lists instead.
Here is the type list implementation.
/* Our empty node for our type list. */
class Empty {};
/* Cons for our type list. */
template <typename First_, typename Rest_>
class Cons {
public:
/* First type */
typedef First_ First;
/* Rest. */
typedef Rest_ Rest;
}; // Cons<First_, Rest_>
Here is the generic visitor implementation.
/* Forward declaration. */
template <template <typename> class Decorator, typename Members>
class VisitorRecur;
/* Base case. */
template <template <typename> class Decorator, typename Member>
class VisitorRecur<Decorator, Cons<Member, Empty> > {
public:
/* Pure virtual for each of the members. */
virtual void operator()(
typename Decorator<Member>::Type that) const = 0;
}; // VisitorRecur<Decorator, Member>
/* Recursive case. */
template <template <typename> class Decorator, typename Members>
class VisitorRecur
: public VisitorRecur<Decorator, typename Members::Rest> {
public:
/* Bring the operator()s into scope. */
using VisitorRecur<Decorator, typename Members::Rest>::operator();
/* Pure virtual for each of the members. */
virtual void operator()(
typename Decorator<typename Members::First>::Type that) const = 0;
}; // VisitorRecur<Decorator, typename Members::Rest>
/* Final visitor. */
template <template <typename> class Decorator, typename Members>
class Visitor : public VisitorRecur<Decorator, Members> {
public:
/* Bring the operator()s into scope. */
using VisitorRecur<Decorator, Members>::operator();
}; // Visitor<Decorator, Members>
Here are the two decorators that we'll define.
/* ConstRef. */
template <typename T>
class ConstRef {
public:
typedef const T & Type;
}; // ConstRef<T>
/* Ref. */
template <typename T>
class Ref {
public:
typedef T & Type;
}; // Ref<T>
Here is the use case for it.
/* Forward declarations. */
class Circle;
class Square;
class Triangle;
/* Add the members into a type list. */
typedef Cons<Circle, Cons<Square, Cons<Triangle, Empty> > > Members;
/* Our const visitor which accepts the members by const-ref. */
typedef Visitor<ConstRef, Members> ConstVisitor;
/* Our mutating visitor which accepts the members by ref. */
typedef Visitor<Ref, Members> MutatingVisitor;
Related
What is the base class exactly in this case?
I have some difficulty to grab the full meaning of the first inheritance, due to the FieldType::template and RecordPolicy<N>
template<
class N,
class FieldType
>
class FieldDefinition:
public FieldType::template RecordPolicy<N>
{
public:
typedef typename FieldType::GetSetPolicy::Type Type;
typedef typename FieldType::GetSetPolicy::MemoryType MemoryType;
typedef FieldType FieldClass;
};
Usage:
template<class ObjectClass_, class Schema_>
class Object:
public virtual ObjectBase,
public FieldDefinition<ObjectClass_, PointerField<ObjectClass_> >
{
//...
}
Others:
template<class T> class PointerField;
template<class T>
class PointerField
{
public:
//...
template<class N>
class RecordPolicy : public SerializedField<N, PointerField<T> > {};
};
The full hierarchy of Object<Foo, Bar> is:
Object<Foo, Bar>
virtual ObjectBase
FieldDefinition<Foo, PointerField<Foo>>
PointerField<Foo>::RecordPolicy<Foo>
SerializedField<Foo, PointerField<Foo>>
In particular, note that FieldType::template RecordPolicy<N> base clause. This means that FieldDefinition expects whatever class is supplied as FieldType (in your case, PointerField<Foo>) to have a nested template named RecordPolicy with a single type template parameter, for which N (in your case, Foo again) will be substituted. The class derives from the result of this instantiation, in your case the nested class PointerField<Foo>::RecordPolicy<Foo>, which in turn has another base class.
Seemed like a good strategy to compose my objects like this (as policies):
template<typename FluxType, typename SourceType>
class Model : public FluxType, public SourceType
{ };
//later in the code:
template<typename FluxType, typename SourceType>
class ConcreteModel : public Model<FluxType, SourceType>
{};
However, FluxType and SourceType are classes that use the same data. So I had used virtual inheritance:
class ConcreteModelProps{};
class ConcreteFlux : virtual public ConcreteModelProps
{};
class ConcreteFlux2 : virtual public ConcreteModelProps
{/*sligthly different implementation*/};
class ConcreteSource : virtual public ConcreteModelProps
{};
class DefaultSource2
{/*no need for data*/};
That way I could compose my ConcreteModel with different FluxType and SourceType objects.
ConcreteModel<ConcreteFlux, DefaultSource2> /*or whatever*/.
The fact is that the the data that are defined in ConcreteModelProps are closely related to ConcreteModel. It seems to me that I'm doing at least something wrong. How can I make this design better? Preferably without the virtual inheritance?
thx, dodol
Well, it's simple: you are violating the LISKOV Substitution Principle by having ConcreteFlux inherit from ConcreteModelProps; so it's only right you pay the price.
Now, if you externalized the data, you could be working with a saner model.
template <typename FluxType, typename SourceType>
class Model {
public:
typedef typename FluxType::DataType DataType;
}; // class Model
template <typename M>
class ConcreteModel: public M {
}; // class ConcreteModel
And then:
class ConcreteFlux {
public:
typedef ConcreteModelProps DataType;
};
class ConcreteSource {
public:
typedef ConcreteModelProps DataType;
};
template <typename Data>
class DefaultSource {
typedef Data DataType;
};
With finally:
class ConcreteModel<Model<ConcreteFlux, ConcreteSource>> {};
Of course, this means that now all methods of ConcreteFlux and ConcreteSource need be passed the handle to ConcreteModelProps in each of their method. That's what externalization was about.
As a simplified example, if I have the classes
template <class T, class U> class ProcessEvent
{
public:
ProcessEvent(T* t) : var1(t) { var2 = new U; }
Process() { var2->Process(var1); }
private:
T* var1;
U* var2;
};
class Foo
{
/*data*/
};
class FooProcessor
{
void Process(Foo* foo) {/*functionality*/}
};
class Bar
{
/*data*/
};
class BarProcessor
{
void Process(Bar* bar) {/*functionality*/}
};
So the class ProcessEvent can take have two different sets of template types,
ProcessEvent<Foo, FooProcessor>
ProcessEvent<Bar, BarProcessor>
However, the second template type FooProcessor and BarProcessor are directly implied by the first template type and are implementation details the user doesn't care about. My goal is to have the same functionality as above, but have ProcessEvent take only a single template parameter, Foo or Bar. Other than through specialization of ProcessEvent, can this be done?
I'm going to assume that you simplified for clarity and are reallyusing smart pointers or at least properly managing the memory.
The easiest way to do this is with a typedef in the first class:
class Foo
{
typedef FooProcessor Processor;
// Stuff.
};
Then in your template get rid of U and use typename T::Processor instead.
You can do this as follows:
template<typename T>
class Spec
{
};
template<>
class Spec<Foo>
{
typedef FooProcessor type;
};
template<>
class Spec<Bar>
{
typedef BarProcessor type;
};
Then use Spec<T>::type, with T=Bar or T=Foo, whenever you need BarProcessor and FooProcessor, respectively.
I would assume that a FooProcessor can only process Foo and a BarProcessor can only process Bar, but the other types could have more than one processor class. Thus you could do it intrusively:
class FooProcessor
{
public:
typedef Foo value_type;
};
class BarProcessor
{
public:
typedef Bar value_type;
};
You could use polymorphism:
template< typename T >
class Processor
{
public:
typedef T value_type;
virtual ~Processor() {}
virtual void process( value_type * ) = 0;
};
class FooProcessor : public Processor<Foo>
{
// implement process
};
You could use an adapter class like Matt Phillips's but in reverse, so it takes the process class as template parameter:
template<typename T>
class Spec
{
};
template<> class Spec<FooProcessor>
{
typedef Foo type;
};
template<> class Spec<Bar>
{
typedef BarProcessor type;
};
With intrusive typing and the Spec adapter typing your ProcessEvent template would take the processor type as parameter and derive the other one using value_type or type.
With polymorphism, your ProcessEvent would take the object type as parameter (Foo or Bar) and would be passed a processor that derives from Processor or Processor to process events.
If there are huge numbers of events to process and it is always processing them with the same object, the latter method would of course be slightly less efficient as it is processing through a v-table. It depends partly how long they take to process and whether the function that does it could be inlined.
In the CRTP pattern, we run into problems if we want to keep the implementation function in the derived class as protected. We must either declare the base class as a friend of the derived class or use something like this (I have not tried the method on the linked article). Is there some other (simple) way that allows keeping the implementation function in the derived class as protected?
Edit: Here is a simple code example:
template<class D>
class C {
public:
void base_foo()
{
static_cast<D*>(this)->foo();
}
};
class D: public C<D> {
protected: //ERROR!
void foo() {
}
};
int main() {
D d;
d.base_foo();
return 0;
}
The above code gives error: ‘void D::foo()’ is protected with g++ 4.5.1 but compiles if protected is replaced by public.
It's not a problem at all and is solved with one line in derived class:
friend class Base< Derived >;
#include <iostream>
template< typename PDerived >
class TBase
{
public:
void Foo( void )
{
static_cast< PDerived* > ( this )->Bar();
}
};
class TDerived : public TBase< TDerived >
{
friend class TBase< TDerived > ;
protected:
void Bar( void )
{
std::cout << "in Bar" << std::endl;
}
};
int main( void )
{
TDerived lD;
lD.Foo();
return ( 0 );
}
As lapk recommended, problem can be solved with simple friend class declaration:
class D: public C<D> {
friend class C<D>; // friend class declaration
protected:
void foo() {
}
};
However, that exposes all protected/private members of derived class and requires custom code for each derived class declaration.
The following solution is based on the linked article:
template<class D>
class C {
public:
void base_foo() { Accessor::base_foo(derived()); }
int base_bar() { return Accessor::base_bar(derived()); }
private:
D& derived() { return *(D*)this; }
// accessor functions for protected functions in derived class
struct Accessor : D
{
static void base_foo(D& derived) {
void (D::*fn)() = &Accessor::foo;
(derived.*fn)();
}
static int base_bar(D& derived) {
int (D::*fn)() = &Accessor::bar;
return (derived.*fn)();
}
};
};
class D : public C<D> {
protected: // Success!
void foo() {}
int bar() { return 42; }
};
int main(int argc, char *argv[])
{
D d;
d.base_foo();
int n = d.base_bar();
return 0;
}
PS: If you don't trust your compiler to optimize away the references, you can replace the derived() function with the following #define (resulted in 20% fewer lines of disassembly code using MSVC 2013):
int base_bar() { return Accessor::base_bar(_instance_ref); }
private:
#define _instance_ref *static_cast<D*>(this) //D& derived() { return *(D*)this; }
After some I came with a solution that works event for private members of templated derived classes. It does not solves the problem of not exposing all the members of the derived class to the base, since it uses a friend declaration on the whole class. On the other hand, for the simple case, this does not requires repeating the base name, nor it's template parameters and will always work.
First the simple case when the derived is non-template. The base takes an additional void template parameter just to show that everything still works in the case of extra template parameters of the base. The only needed one, as per the CRTP, is the typename Derived.
//Templated variadic base
template <typename Derived, typename...>
struct Interface
{
using CRTP = Interface; //Magic!
void f() { static_cast<Derived*>(this)->f(); }
};
//Simple usage of the base with extra types
//This can only be used when the derived is NON templated
class A : public Interface<A, void>
{
friend CRTP;
void f() {}
};
The only thing needed for this to work is the using CRTP = Interface; declaration in the base and the friend CRTP; declaration in the derived.
For the case when the derived is itself templated the situation is trickier. It took me some time to come to the solution, and I'm sure it's still not perfect.
Most of the magic happens inside these templates:
namespace CRTP
{
template <template <typename, typename...> class _Base, typename _Derived, typename... _BaseArgs>
struct Friend { using Base = _Base<_Derived, _BaseArgs...>; };
template <template <typename, typename...> class _Base, typename ..._BaseArgs>
struct Base
{
template <template <typename...> class _Derived, typename... _DerivedArgs>
struct Derived : public _Base<_Derived<_DerivedArgs...>, _BaseArgs...> {};
};
}
Their usage is more or less straightforward. Two use the above templates several steps are needed.
First, when inheriting in the derived class the inherited-from base class, and it's optional parameters, needs to be given. This is done using CRTP::Base<MyBase, BaseOptional....>, where MyBase is the name of the class used for CRTP, and the BaseOptional... are template parameters that are passed to the base class as-is, directly after passing our derived class that is supplied in the next step. When the base class does not accepts any additional template parameters they can be omitted completely: CRTP::Base<MyBase>.
The next step is to introduce the derived class (the whole point of CRTP). This is done by following the above CRTP::Base<...> with a ::Derived<ThisDerived, DerivedOptional...>. Where ThisDerived is the class this is defined in, and DerivedOptional... are all the template parameters declared in this class'es template declaration. The optional parameters much be specified exactly as they appear in the class template declaration.
The last step is declaring the base class as a friend. This is done by declaring friend typename CRTP::Friend<MyBase, ThisDerived, BaseOptional...>::Base somewhere in the class. The BaseOptional... template perameters must be repeated exactly as they appear in the CRTP::Base<MyBase, BaseOptional...> that is inherited from.
Follows is an example of using a templated derived when the base does not depends on the templated types (but it still can take other template parameters, void in this example).
//Templated derived with extra, non-dependant types, passed to the base
//The arguments passed to CRTP::Base::Derived<, ARGS> must exactly match
// the template
template <typename T, typename... Args>
class B : public CRTP::Base<Interface, void>::Derived<B, T, Args...>
{
friend typename CRTP::Friend<Interface, B, void>::Base;
void f() {}
};
Next is an example for when the base depends on template parameters of the derived. The only difference from the previous example is the template keyword. An experiment shows that if the keyword is specified for the previous, non dependant, case the code also complies cleanly.
//Templated derived with extra dependant types passed to the base
//Notice the addition of the "template" keyword
template <typename... Args>
class C : public CRTP::Base<Interface, Args...>::template Derived<C, Args...>
{
friend typename CRTP::Friend<Interface, C, Args...>::Base;
void f() {}
};
Please note that these templates do not work for non-templated derived classes. I will update this answer when I find the solution, so a unified syntax could be used for all cases. The closest thing that can be done is just using some fake template parameter. Note that it still must be named and passed to the CRTP machinery. For example:
template <typename Fake = void>
class D : public CRTP::Base<Interface>::Derived<D, Fake>
{
friend typename CRTP::Friend<Interface, D>::Base;
void f() {}
};
Note that A, B, C & D are declared as class. That is, all their members are private.
Follows is some code that uses the above classes.
template <typename... Args>
void invoke(Interface<Args...> & base)
{
base.f();
}
int main(int, char *[])
{
{
A derived;
//Direct invocation through cast to base (derived.f() is private)
static_cast<A::CRTP &>(derived).f();
//Invocation through template function accepting the base
invoke(derived);
}
{
B<int> derived;
static_cast<B<int>::CRTP &>(derived).f();
invoke(derived);
}
{
C<void> derived;
static_cast<C<void>::CRTP &>(derived).f();
invoke(derived);
}
{
D<void> derived;
static_cast<D<>::CRTP &>(derived).f();
invoke(derived);
}
return 0;
}
The invoke free-standing templated function works for any class derived from the base.
Also shown is how to cast the derived to the base without the need to actually specify the name of the base.
Surprisingly, this does not depend on any system headers.
The full code is available here: https://gist.github.com/equilibr/b27524468a0519aad37abc060cb8bc2b
Comments and corrections are welcome.
I'm using my class as a template parameter of one of its parent class, and that parent class uses it in a template argument (though sizeof()).
And the compiler gives me:
error : incomplete type 'Invoker::workerClass {aka MyClass}' used in nested name specifier
Yet the class is well defined in the file. I guess this is because the child class isn't instantiated at the moment of the base class' instantiation, yet that kind of thing happens with CRTP and there's no problems.
The reason I use the child class in the template argument is to do a different function call if the child class has, or doesn't have, a specific function.
Here's a minimal code for testing
/* Structure similar to boost's enable if, to use
SFINAE */
template <int X=0, class U = void>
struct test {
typedef U type;
};
enum Commands {
Swim,
Fly
};
/* Structure used for template overloading,
as no partial function template specialization available */
template<Commands T>
struct Param {
};
template <class T>
class Invoker
{
public:
typedef T workerClass;
workerClass *wc() {
return static_cast<workerClass*>(this);
}
template <Commands command>
void invoke() {
invoke2(Param<command>());
}
/* If the child class has those functions, call them */
/* Needs template paramter Y to apply SFINAE */
template<class Y=int>
typename test<sizeof(Y)+sizeof(decltype(&workerClass::fly))>::type
invoke2(Param<Fly>) {
wc()->fly();
}
template<class Y=int>
typename test<sizeof(Y)+sizeof(decltype(&workerClass::swim))>::type
invoke2(Param<Swim>) {
wc()->shoot();
}
template<Commands command>
void invoke2(Param<command>) {
/* Default action */
printf("Default handler for command %d\n", command);
}
};
template <class T, class Inv = Invoker<T> >
class BaseClass : public Inv
{
public:
template<Commands command>
void invoke() {
Inv::template invoke<command>();
}
};
class MyClass : public BaseClass<MyClass>
{
public:
void swim() {
printf("Swimming like a fish!\n");
}
/* void fly(); */
};
void testing() {
MyClass foo;
foo.invoke<Fly>(); /* No 'void fly()' in MyClass, calls the default handler */
foo.invoke<Swim>(); /* Should print the swimming message */
}
The error happens at the line:
typename test<sizeof(Y)+sizeof(decltype(&workerClass::fly))>::type
So, is there any compiler that supports this, or is this explicitely specified by the standard as an invalid use of templates? Do I have to change the way I'm doing this and find a way around? CRTP is giving me hope the code might be valid, but I'm not sure.
If this really isn't possible, then why exactly, and why does CRTP work?
The solution was, as ildjarn pointed out, to add another level of indirection.
That is done by changing the test function to accept types:
template <typename X, class U = void>
struct test {
typedef U type;
};
And then pass the child class as a template parameter, instead of specifying it from the get go:
template<class Y=workerClass>
typename test<decltype(&Y::fly)>::type
invoke2(Param<Fly>) {
wc()->fly();
}
template<class Y=workerClass>
typename test<decltype(&Y::swim)>::type
invoke2(Param<Swim>) {
wc()->swim();
}
That way the nested specifier is evaluated only when the function is called and not at the class evaluation, and by that time the child class is already evaluated. Plus with the possibility to pass default template argument, we can call the function without any template parameters.
The template is also much more readable now. And the sample code works just fine now:
class MyClass : public BaseClass<MyClass>
{
public:
void swim() {
printf("Swimming like a fish!\n");
}
/* void fly(); */
};
void testing() {
MyClass foo;
foo.invoke<Fly>(); /* No 'void fly()' in MyClass, calls the default handler */
foo.invoke<Swim>(); /* Should print the swimming message */
}