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.
Related
Often in derived template classes I need to refer to the base to access members. I end up writing code like this:
template<typename A>
struct BaseClass
{
};
template<typename B>
struct Derived : public BaseClass<int>
{
using Base = BaseClass<int>;
};
This gets more verbose and harder to maintain for a large number of classes with a lot of template arguments.
Is there a cleaner way to import base symbols in this case?
I think you can do things the other way i.e. defer the base resolution to the base class instead, so that it would be automatically resolved for any new derived class without bothering of rewriting it for each one.
Something like:
template <typename A>
struct BaseClass
{
using Base = BaseClass<A>;
};
template <typename B>
struct Derived : public BaseClass<int>
{};
Live example
If Derived is not itself a template class: You can simply use BaseClass (the inherited injected-class-name):
struct Derived : public BaseClass<int>
{
void f()
{
BaseClass::f();
}
};
If it is also a template, using Base = BaseClass<int>; is probably the best way.
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.
Hi I am not sure that this is possible since but I thought of asking since there might be better ways of achieving something similar that I am not aware of.
For simplicity lets just consider that VectorT is
template<class T>
class VectorT: private std::vector<T>`
An attempt to what I wanted to have is something along the lines of.
namespace detail
{
template<class SmartPtr>
class MyClassVectorBase : public VectorT<SmartPtr>
{
public:
MyClassVectorBase() = default;
// all common functions of MyVectorView and MyVector
};
}
using MyClassVectorView = detail::MyClassVectorBase<nonstd::observer_ptr<SomeClass>>;
class MyVector : public detail::MyClassVectorBase<std::unique_ptr<SomeClass>>
{
// only functions related to the actual owner vector
};
What I am hoping is that MyClassVectorBase can be templated only on the smart pointer type and only accept SomeClass.
I thought that it might be possible with a specialization but I got no idea what the syntax for something like that would be
template<class T, class SmartPtr>
class MyClassVectorBase : public VectorT<SmartPtr<T>>
{
};
template<SomeClass T, typename SmartPtr>
class MyClassVectorBase : public VectorT<SmartPtr<T>>
{
};
Is something like that even possible ?
Edited:
Ok let me try to explain this and the logic behind it. I need to have a VectorT of Foo objects. Only Foo and nothing else.
In one case the class will be the owner of the objects and have a few extra functions.
Since it is the owner it will be class MyClassVector : public VectorT<std::unique_ptr<Foo>>
Then I have to somehow operate on these objects but these wont be owned.
The ownership is single and will always outlive the object that I will operate on so no need for shared_ptr.
So Then I guess my class will be a "View class" MyClassVectorView : public VectorT<std::observer_ptr<Foo>>
Instead of observer_ptr it could as well be say raw ptr but the intent is better with it.
Now MyClassVectorView will have all identical functions with MyClassVector which is why I think that I would be inheriting from it.
To do so I need to have a base class that will accept both unique_ptr and observer_ptr.
Then I can avoid duplication so long as I can do MyClassVector : public MyClassVectorView<std::unique_ptr<Foo>>
The alterantive would be have one class and detect with SFINAE if the template parameter is a unique_ptr and then enable the extra functions. This would avoid the extra inheritance.
Not sure about what you want to obtain but I suspect that you need template template parameters.
I suppose you could declare (but not define) MyClassVectorBase as receiving a single template typename parameter
template <typename>
class MyClassVectorBase;
and next define a specialization template-template based; something like
template <template<typename...> class SmartPtr, typename Foo>
class MyClassVectorBase<SmartPtr<Foo>> : public VectorT<SmartPtr<Foo>>
{
public:
MyClassVectorBase() = default;
void doSomething(){}
void doSomething2(){}
};
If Foo isn't a template parameter, but is the Foo struct, you can write
template <template<typename...> class SmartPtr>
class MyClassVectorBase<SmartPtr<Foo>> : public VectorT<SmartPtr<Foo>>
{
public:
MyClassVectorBase() = default;
void doSomething(){}
void doSomething2(){}
};
Your example modified and integrated (with a main() and a dummy observer_ptr)
#include <iostream>
#include <string>
#include <vector>
#include <memory>
namespace nonstd
{
template <typename T>
struct observer_ptr
{ };
}
template <class T>
class VectorT
{
public:
// expose nececssary functions
private :
std::vector<T> container_;
};
struct Foo{
double x;
};
template <typename>
class MyClassVectorBase;
// this class should only accept smart pointers of Foo
template <template<typename...> class SmartPtr, typename Foo>
class MyClassVectorBase<SmartPtr<Foo>> : public VectorT<SmartPtr<Foo>>
{
public:
MyClassVectorBase() = default;
void doSomething(){}
void doSomething2(){}
};
using MyClassVectorView = MyClassVectorBase<nonstd::observer_ptr<Foo>>;
class MyVector : public MyClassVectorBase<std::unique_ptr<Foo>>
{
// function only for this class but still inheriting all MyClassVectorBase stuff
};
int main ()
{
}
Let's say I have the following:
class Base
{
protected:
Base() { }
};
class A : public Base
{
};
class B : public Base
{
};
Now suppose I do this with a template:
TemplatedClass<Base> *generic = new TemplatedClass<A>();
It doesn't work, and I believe I understand why, but I'd like to know if I can do something equivalent. I have several template specializations of the form
typedef TemplatedClass<A> ASpec;
typedef TemplatedClass<B> BSpec;
typedef TemplatedClass<C> CSpec;
I have a single variable whose type I'd like to defer until runtime, so that I can dynamically assign it like
if(condition1)
generic = new ASpec();
else if(condition2)
generic = new BSpec();
Is there any way to go about this? I don't have the ability to change the fact that the classes are templated and not inheriting from a base class, or I'd just do that.
This is not possible in C++.
The fact that A derives from Base doesn't mean that TemplatedClass<A> derives from TemplatedClass<Base>.
See this Stack Overflow post for alternatives:
Conversion from STL vector of subclass to vector of base class
You can derive TemplatedClass<T> from TemplatedClass<Base>, either by specialising if for Base, or by providing a dummy class like this:
struct Dummy {};
template <typename T>
struct BaseClass<T> {
typedef TemplatedClass<Base> Type;
};
template <>
struct BaseClass<Base> {
typedef Dummy Type;
};
template <typename T>
struct TemplatedClass : BaseClass<T>::Type
{
//...
};
I writing an "Effect" class (for an opengl program) and I'm also attempting to write a container class for.
The Effect class is defined as follows:
template <typename T>
class Effect
{
private:
Vbo<T> m_Vbo;
};
Where T is a type that describes the vertex attributes.
In order to write a container class, I'd like to store these effects in an std::map:
class EffectMgr : public Singleton <EffectMgr>
{
private:
typedef std::map<std::string, Effect<T> & > EffectMap;
};
The error I get with the container class is that T is undefined. Can someone enlighten me?
I may have (by sheer chance and tinkering) have found the answer although I won't know until I've written the container class:
class EffectMgr : public Singleton <EffectMgr>,
{
private:
template <typename T>
typedef std::map<std::string, Effect<T> & > EffectMap;
};
T is scoped within the Effect definition. Outside of the scope T is undefined.
Perhaps you mean this?
template <typename T>
class EffectMgr : public Singleton <EffectMgr>
{
private:
typedef std::map<std::string, Effect<T> & > EffectMap;
};
// use: EffectMgr<type>::EffectMap
If you want only the typedef to be templated then do this:
class EffectMgr : public Singleton <EffectMgr>
{
private:
template <typename T>
using EffectMap = std::map<std::string, Effect<T> & >; // C++11 feature
};
// use: EffectMgr::EffectMap<type>
Since Effect is a template class, and you're not specializing it inside EffectMgr, it also needs to be a template:
template<typename T>
class EffectMgr : public Singleton <EffectMgr>
{
private:
typedef std::map<std::string, Effect<T> & > EffectMap;
};
As I understand, you want to store effects with a different T-ypes in a map.
If it is, the simplest way would be specify interface
class IEffect
{
public:
virtual ~IEffect() = 0;
}
IEffect::~IEffect()
{
}
and implement it in your template:
template <typename T>
class Effect: public IEffect
{
private:
Vbo<T> m_Vbo;
};
now, you can create std::map<std::string, IEffect* >
With additional effort, you can write a wrapper over IEffect to get rid of pointers.