I have a hierarchy of nodes, where "diamond" can occurred.
Every node must be clonable but I don't want to write clone method to every node. So I use CRTP.
class Node
{
public:
Node(){}
Node(Fill*) { }
virtual ~Node() {}
virtual Node * clone() const = 0;
virtual void id() { std::cout << "Node\n"; }
};
//====================================================================
template <typename Base, typename Derived>
class NodeWrap : public Base
{
public:
NodeWrap() { }
NodeWrap(Fill * arg1) : Base(arg1) { }
virtual Node *clone() const
{
return new Derived(static_cast<Derived const &>(*this));
}
};
works as follows:
class NodeA : public NodeWrap<Node, NodeA>
{
public:
typedef NodeWrap<Node, NodeA> BaseClass;
NodeA() { }
NodeA(Fill * f) : BaseClass(f) { }
virtual void id() { std::cout << "NodeA\n"; }
};
First question:
There is know BUG in VS when "covariance is used with virtual inheritance".
Is there a way to overcome the bug, and still have covariant types is clone method?
I changed return type to be Node instead of Base. I can live with that, but I would like to have Base as return type
Second question:
Problem occurred when multiple inheritance comes to play. I created new wrapper, which inherits virtually
template <typename Base, typename Derived>
class NodeWrapVirtual : public virtual Base
{
public:
NodeWrapVirtual() { }
NodeWrapVirtual(Fill * arg1) : Base(arg1) { }
virtual Node *clone() const
{
return new Derived(static_cast<Derived const &>(*this));
}
};
and now building diamond structure:
class NodeB : public NodeWrapVirtual<Node, NodeB>
{
public:
typedef NodeWrapVirtual<Node, NodeB> BaseClass;
NodeB() { }
NodeB(Fill * f) : BaseClass(f) { }
virtual void id() { std::cout << "NodeB\n"; }
};
//====================================================================
class NodeC : public NodeWrapVirtual<Node, NodeC>
{
public:
typedef NodeWrapVirtual<Node, NodeC> BaseClass;
using BaseClass::clone;
NodeC() { }
NodeC(Fill * f) : BaseClass(f) { }
virtual void id() { std::cout << "NodeC\n"; }
};
and problematic diamond node:
class NodeD : public NodeWrap<NodeB, NodeD>,
public NodeWrap<NodeC, NodeD>
{
public:
typedef NodeWrap<NodeB, NodeD> BaseClassB;
typedef NodeWrap<NodeC, NodeD> BaseClassC;
NodeD() { }
NodeD(Fill * f) : BaseClassB(f), BaseClassC(f) { }
using BaseClassB::clone; // (1)
virtual NodeD *clone() const { return new NodeD(*this); } // (2)
virtual void id() { std::cout << "NodeD\n"; }
};
where are 2 lines I am curious about. (line (1) and (2))
If both lines are removed, there is oblivious compile error, because there is ambiguous clone method (from every parent). Since I don't use covariant return types, there should work clone method form each parent, so i use line (1) but it doesn't work. Still ambiguous.
So I use line (2) and it works.
Is there a nice way, to avoid writing line (2)?
HERE is full working example on ideone.
First you should be very carefull to use virtual inheritance with members inside the virtual base (look at https://stackoverflow.com/a/1193516/1918154, "Effective C++", item 20: "Avoid data members in public interfaces" and http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.8). Your node gets an pointer to a fill which is not used, but it looks like you need it somewhere.
Your problem can be solved when you move the inhertance relationship (public virtual and public) in the base class for your NodeWrap.
template <typename Base>
class InheritVirtual
: public virtual Base
{};
template <typename... Bases>
class InheritBases
: public Bases...
{
virtual Node* clone() const = 0;
virtual void id() const = 0;
};
class NodeB : public NodeWrap<InheritVirtual<Node>, NodeB>
{
//...
};
class NodeC : public NodeWrap<InheritVirtual<Node>, NodeB>
{
//...
};
class NodeD : public NodeWrap<InheritBases<NodeB,NodeC>, NodeD>
{
//...
};
Running Example.
The pure virtual methods in InheritBases are needed because the so called domination rule (Dominance in virtual inheritance).
The problem to be solved is a way to transfer paramters to the right constructor in case of multiple bases. Unlike Node (wich is a virtual base) it is ok to let NodeB and NodeC have member variables and non trivial constructors.
Each virtual function must have a unique final overrider in each derived class. This has nothing to do with name lookup (the requirement is for the functions, not for their names), thus using is irrelevant.
Use a multi-base-classed node class template:
template <class Derived, class Base1, class Base2>
class node2 : // etc
// or use a variadic template if you have more than two bases
As for covariant returns, they are strictly unnecessary, if convenient. You can always split each virtual function into a private virtual and a public non-virtual. This comes handy if you want to return covariant smart pointers, which is not supported by the regular covariant return machinery at all.
Related
I've got a class Base from which I have two classes, DerivedA and DerivedB as defined below.
template <typename Derived>
class Base{
public:
double interface(){
static_cast<Derived*>(this)->implementation();
}
};
class DerivedA : public Base<DerivedA>{
public:
double implementation(){ return 2.0;}
};
class DerivedB : public Base<DerivedB>{
public:
double implementation(){ return 1.0;}
};
In short, I'm trying to do the following to maintain a collection of objects, some of which are DerivedA and some of which are DerivedB:
std::vector<std::shared_ptr<Derived>>
Which is obviously impossible beacuse I've now made the class Derived a templated class.
Is there any way I can create / maintain a polymorphic collection of objects?
EDIT: Unfortunately, a simple templated structure does not work as the function implementation is templated in my actual program -- so then implementation would have to be a templated pure virtual function, which cannot be. Pardon my lack of explanation.
This answer pertains to the question as it was at the time of this answer.
Don't use CRTP, which is not dynamic polymorphism, to create dynamic polymorphism.
Use a virtual function.
That's what they're for.
class Base
{
private:
virtual
auto implementation() -> double = 0;
public:
auto interface() -> double { return implementation(); }
};
class DerivedA
: public Base
{
private:
auto implementation() -> double override { return 2.0; }
};
class DerivedB
: public Base
{
private:
auto implementation() -> double override { return 1.0; }
};
Alf's suggestion is on target. It is easy to adapt it to your additional requirement. Define an interface with a pure virtual method:
struct BaseInterface {
virtual ~BaseInterface() {}
virtual double interface() = 0;
};
Now, your template base class can derive from the interface:
template <typename Derived>
class Base : BaseInterface {
public:
double interface(){
static_cast<Derived*>(this)->implementation();
}
};
Now, you can create a vector of pointers to the interface:
std::vector<std::shared_ptr<BaseInterface>>
Because Base<DerivedA> is a completely different type compared to Base<DerivedB>, you are right that you can't just do something like std::vector<std::shared_ptr<Base>>, as it would be syntactically invalid and has no meaningful semantics with regards to C++.
One way to achieve what you want and preserve your current CRTP hierarchy is to create a type erasing interface (or is it what it should be called? I'm not sure...). It is basically a wrapper that defines a certain interface in which you could wrap objects that obey that interface.
#include <vector>
#include <memory>
#include <iostream>
class VirtualBase { // Really am not sure what it should be called, sorry
class Interface {
public:
virtual ~Interface() = default;
virtual double get() = 0;
};
template<typename T>
class Impl : public Interface {
T m_impl_obj;
public:
Impl(T impl_obj) : m_impl_obj(std::move(impl_obj)) {}
double get() override {
return m_impl_obj.get();
}
};
std::shared_ptr<Interface> m_obj;
public:
template<typename T>
VirtualBase(T obj) : m_obj(new Impl<T>(std::move(obj))) {}
double get() {
return m_obj->get();
}
};
template <typename Derived>
class Base{
public:
double get(){
return static_cast<Derived*>(this)->implementation();
}
};
class DerivedA : public Base<DerivedA>{
public:
double get(){ return 2.0;}
};
class DerivedB : public Base<DerivedB>{
public:
double get(){ return 1.0;}
};
int main() {
std::vector<VirtualBase> v;
v.emplace_back(DerivedA{});
v.emplace_back(DerivedB{});
for(auto b : v) {
std::cout << b.get() << std::endl;
}
}
Live example
This is quite incomplete, but it should work, at least in my case if I need such a design. An excellent introduction, with explanations and rationales of how and why, is Sean Parent's talk at GoingNative 2013: http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil . Really, you should see it, including all the other great presentations in GoingNative.
Edit: this is based on an assumption that OP actually needs virtual function templates. This is apparently not the case.
It is not possible to have virtual function templates.
One way to partially simulate them is the Visitor pattern. It is often used to add dynamically dispatched functionality to existing classes. The fact that this added functionality can be templatized is overlooked all too often.
A pseudocode example
class Base
{
virtual void accept (Visitor*) = 0;
}
class Derived1 : public Base
{
void accept(Visitor* v) { v->visit(this); }
}
class Derived2 : public Base
{
void accept(Visitor* v) { v->visit(this); }
}
class Visitor
{
virtual void visit (Derived1*) = 0;
virtual void visit (Derived2*) = 0;
}
template<class X, class Y>
class FooVisitor
{
X x; Y y;
FooVisitor(X x, Y y): x(x), y(y) {}
void visit (Derived1*) { x.func(y); }
void visit (Derived2*) { y.otherfunc(x); }
}
Of course all the downsides of Visitor are here as well.
I have a templated SafeSingleton class, Base class which is derived from SafeSingleton and implements some base methods. I want to have class that is derived from Base and can be accessed via instance() method of SafeSingleton. The problem is that when I am trying to access Derived::instance() it returns the pointer to a Base class and the compiler doesn't know anything about methods of derived class. What should I do to make below code work.
template<class T>
class SingleTon {
public:
static T* instance()
{
return holder().instance;
}
protected:
template<class I>
struct Holder
{
Holder() : instance(new I())
{
}
I* instance;
};
static Holder<T> &holder()
{
static Holder<T> holder;
return holder;
}
};
// Hopefully issue is here, I am never creating SingleTon<Derived>, but how can it be done?
class Base : public SingleTon<Base> {
public:
Base() = default;
void printBase() {
std::cout << "Base";
}
};
class Derived : public Base {
public:
Derived() = default;
void printDerived() {
std::cout << "Derived";
}
};
int main()
{
Derived::instance()->printBase();
Derived::instance()->printDerived(); // Here is the error
//Error: main.cpp:57:26: error: ‘class Base’ has no member named ‘printDerived’
//57 | Derived::instance()->printDerived();
return 0;
}
template<class D>
class Base : public SingleTon<D> {
and
class Derived : public Base <Derived>
and ... done?
If you want to put Base's non-Ddependent methods in a cpp file, you'll have to get fancy. Have BaseImp that does not derive from SingleTon, put code there. Have Base<D> derive from it and write forwarding glue to it BaseImpl. But you probably don't need this.
Let a class hierarchy :
class Base { virtual ~Base() throw(); };
class DerivedA : public Base { };
class DerivedB : public Base { };
I would like to have some code specific to each of these derived classes. However that code also being specific to the application that makes use of this class hierarchy, I do not want to embbed this derived-class-specific code into these derived classes. To avoid doing so, I thought about writing free functions :
void DerivedASpecificWork( DerivedA da );
void DerivedBSpecificWork( DerivedB db );
However, when given an instance of a derived class through a reference/pointer to a Base, I do not have access to the actual type of the instance, and thus cannot call the proper Derived*SpecificWork() function.
I would like to know if there is nome kind of design pattern that would allow me to call a derived-class-specific function without knowing the actual type of the instance, i.e having the same mechanism as virtual functions provide, but without having these virtual functions that would require me to embbed application-specific code into that class hierarchy.
Actually, why I want to do that is to provide informations about an exception that occured within a natively implemented function called by a Lua script. Each exception carrying its own set of information, the way I want to represent the error within the script depends on the type of the exception. I could create a pure virtual method in the base class that would be implemented by derived classes, but this would require me to embbed Lua-related code into my exception hierarchy, which I do not want to do since the Lua is specific to one of the application using that exception hierarchy.
Also I cannot use C++11.
Thank you.
May be Brigde pattern can help you.
This pattern can be used when you want to avoid a permanent binding between an abstraction and it's implementation.
(I don't see your comment about your restriction in using c++11, but you can remove std::unique_ptr, std::move and override keyword)
class AppSpecificImp
{
public:
virtual void DoWork() = 0;
};
class Base
{
public:
virtual ~Base() throw();
virtual DoWork() = 0;
};
class DerivedA : public Base
{
public:
DerivedA(std::unique_ptr<AppSpecificImp> appImp)
: imp(std::move(appImp))
{
}
void DoWork() override
{
// DerivedA specific code
imp->DoWork();
}
private:
std::unique_ptr<AppSpecificImp> imp;
};
class DerivedB : public Base
{
public:
DerivedB(std::unique_ptr<AppSpecificImp> appImp)
: imp(std::move(appImp))
{
}
void DoWork() override
{
// DerivedB specific code
imp->DoWork();
}
private:
std::unique_ptr<AppSpecificImp> imp;
};
Edit to show Visitor pattern usage:
With visitor pattern you can do what you want but with more Effort.
class Visitor
{
public:
virtual void VisitDerivedA(DerivedA* object) = 0;
virtual void VisitDerivedB(DerivedB* object) = 0;
};
class Base
{
public:
virtual void Visit(Visitor* visitor) = 0;
};
class DerivedA : public Base
{
public:
virtual void Visit(Visitor* visitor)
{
visitor->VisitDerivedA(this);
}
};
class DerivedB : public Base
{
public:
virtual void Visit(Visitor* visitor)
{
visitor->VisitDerivedB(this);
}
};
class AppSpecificVisitor : public Visitor
{
public:
void VisitDerivedA(DerivedA* object)
{
// Do any work related to DerivedA class
}
void VisitDerivedB(DerivedB* object)
{
// Do any work related to DerivedB class
}
}
int main()
{
AppSpecificVisitor myVisitor;
Base* myBase = // any class in your hierarchy
myBase->Visit(&myVisitor);
}
As I said in comments with Visitor pattern you can add new functionally without changing the main hierarchy(Base->Derived types). You just define a new visitor implementation and write your logic for every class in main hierarchy. In your example you can pack app specific logic in an object and reference that in your derived objects that is an easier approach.
Why not using a new set of hierarchy for application specific implementation ?
class AppBase
{
public:
virtual ~AppBase() throw();
virtual void work_with_app() = 0;
};
class Base
{
public:
Base(AppBase& app) : m_app(app) {}
virtual ~Base() throw();
protected:
AppBase& m_app;
};
class DerivedA : public Base { DerivedA(AppBase& app) : Base(app) {} };
class DerivedB : public Base { DerivedA(AppBase& app) : Base(app) {} };
// Application specific implementation :
class AppLuaSpecific : public AppBase
{
public:
void work_with_app() { /* Lua app specific */ }
};
This way, your 1st hierarchy : Base, DerivedA, DerivedB can live without knowing anything about the app specific code implemented in AppLuaSpecific.
You can implement your own app-specific dispatch as follows (check it live on Coliru):
#include <iostream>
#include <typeinfo>
struct Base { virtual ~Base() {} };
struct DerivedA : public Base { };
struct DerivedB : public Base { };
namespace AppSpecific
{
template<class F>
void dispatch(const Base& b)
{
const std::type_info& t = typeid(b);
if ( t == typeid(DerivedA) )
F::doit(static_cast<const DerivedA&>(b));
else if ( t == typeid(DerivedB) )
F::doit(static_cast<const DerivedB&>(b));
}
struct Foo
{
static void doit(const DerivedA& da) { std::cout << "Foo(DerivedA)\n"; }
static void doit(const DerivedB& db) { std::cout << "Foo(DerivedB)\n"; }
};
struct Bar
{
static void doit(const DerivedA& da) { std::cout << "Bar(DerivedA)\n"; }
static void doit(const DerivedB& db) { std::cout << "Bar(DerivedB)\n"; }
};
} // namespace AppSpecific
int main()
{
DerivedA da;
DerivedB db;
Base& b1 = da;
Base& b2 = db;
AppSpecific::dispatch<AppSpecific::Foo>(b1);
AppSpecific::dispatch<AppSpecific::Foo>(b2);
AppSpecific::dispatch<AppSpecific::Bar>(b1);
AppSpecific::dispatch<AppSpecific::Bar>(b2);
}
I've got a class Base from which I have two classes, DerivedA and DerivedB as defined below.
template <typename Derived>
class Base{
public:
double interface(){
static_cast<Derived*>(this)->implementation();
}
};
class DerivedA : public Base<DerivedA>{
public:
double implementation(){ return 2.0;}
};
class DerivedB : public Base<DerivedB>{
public:
double implementation(){ return 1.0;}
};
In short, I'm trying to do the following to maintain a collection of objects, some of which are DerivedA and some of which are DerivedB:
std::vector<std::shared_ptr<Derived>>
Which is obviously impossible beacuse I've now made the class Derived a templated class.
Is there any way I can create / maintain a polymorphic collection of objects?
EDIT: Unfortunately, a simple templated structure does not work as the function implementation is templated in my actual program -- so then implementation would have to be a templated pure virtual function, which cannot be. Pardon my lack of explanation.
This answer pertains to the question as it was at the time of this answer.
Don't use CRTP, which is not dynamic polymorphism, to create dynamic polymorphism.
Use a virtual function.
That's what they're for.
class Base
{
private:
virtual
auto implementation() -> double = 0;
public:
auto interface() -> double { return implementation(); }
};
class DerivedA
: public Base
{
private:
auto implementation() -> double override { return 2.0; }
};
class DerivedB
: public Base
{
private:
auto implementation() -> double override { return 1.0; }
};
Alf's suggestion is on target. It is easy to adapt it to your additional requirement. Define an interface with a pure virtual method:
struct BaseInterface {
virtual ~BaseInterface() {}
virtual double interface() = 0;
};
Now, your template base class can derive from the interface:
template <typename Derived>
class Base : BaseInterface {
public:
double interface(){
static_cast<Derived*>(this)->implementation();
}
};
Now, you can create a vector of pointers to the interface:
std::vector<std::shared_ptr<BaseInterface>>
Because Base<DerivedA> is a completely different type compared to Base<DerivedB>, you are right that you can't just do something like std::vector<std::shared_ptr<Base>>, as it would be syntactically invalid and has no meaningful semantics with regards to C++.
One way to achieve what you want and preserve your current CRTP hierarchy is to create a type erasing interface (or is it what it should be called? I'm not sure...). It is basically a wrapper that defines a certain interface in which you could wrap objects that obey that interface.
#include <vector>
#include <memory>
#include <iostream>
class VirtualBase { // Really am not sure what it should be called, sorry
class Interface {
public:
virtual ~Interface() = default;
virtual double get() = 0;
};
template<typename T>
class Impl : public Interface {
T m_impl_obj;
public:
Impl(T impl_obj) : m_impl_obj(std::move(impl_obj)) {}
double get() override {
return m_impl_obj.get();
}
};
std::shared_ptr<Interface> m_obj;
public:
template<typename T>
VirtualBase(T obj) : m_obj(new Impl<T>(std::move(obj))) {}
double get() {
return m_obj->get();
}
};
template <typename Derived>
class Base{
public:
double get(){
return static_cast<Derived*>(this)->implementation();
}
};
class DerivedA : public Base<DerivedA>{
public:
double get(){ return 2.0;}
};
class DerivedB : public Base<DerivedB>{
public:
double get(){ return 1.0;}
};
int main() {
std::vector<VirtualBase> v;
v.emplace_back(DerivedA{});
v.emplace_back(DerivedB{});
for(auto b : v) {
std::cout << b.get() << std::endl;
}
}
Live example
This is quite incomplete, but it should work, at least in my case if I need such a design. An excellent introduction, with explanations and rationales of how and why, is Sean Parent's talk at GoingNative 2013: http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil . Really, you should see it, including all the other great presentations in GoingNative.
Edit: this is based on an assumption that OP actually needs virtual function templates. This is apparently not the case.
It is not possible to have virtual function templates.
One way to partially simulate them is the Visitor pattern. It is often used to add dynamically dispatched functionality to existing classes. The fact that this added functionality can be templatized is overlooked all too often.
A pseudocode example
class Base
{
virtual void accept (Visitor*) = 0;
}
class Derived1 : public Base
{
void accept(Visitor* v) { v->visit(this); }
}
class Derived2 : public Base
{
void accept(Visitor* v) { v->visit(this); }
}
class Visitor
{
virtual void visit (Derived1*) = 0;
virtual void visit (Derived2*) = 0;
}
template<class X, class Y>
class FooVisitor
{
X x; Y y;
FooVisitor(X x, Y y): x(x), y(y) {}
void visit (Derived1*) { x.func(y); }
void visit (Derived2*) { y.otherfunc(x); }
}
Of course all the downsides of Visitor are here as well.
template <class CollectionItem>
class Collection
{
void A();
// Many other utility functions
}
class ICollection
{
virtual void B() = 0;
}
class Base : public Collection<BaseItem>, public IBase
{
virtual void B();
}
Is there any way of offering Collection functions via ICollection interface without wrapping all the functions in Base class? ICollection : public Collection<CollectionItem> is not an option.
Bounty Update:
OK, so the original idea was to have Interface to all Collection classes. Before we continue, every CollectionItem also has Interface, let's call it ICollectionItem and ICollection only knows about ICollectionItem.
So what I did was create another template class as Interface to Collection template class - ICollection (pure virtual) accepting ICollectionItem(s). Collection class inherits this interface.
Every Collection class (inheriting Collection<CollectionItem> class) would also inherit it's Interface Collection class. That Interface then virtual inherits ICollection<ICollectionItem>. I'll just post the code :)
Here is the code:
template <class ICollectionItem>
class ICollection
{
public:
virtual const ICollectionItem* At(const int idx) = 0;
};
template <class CollectionItem, class ICollectionItem>
class Collection
: public ICollection,
public virtual ICollection<ICollectionItem> // Weak point
{
private:
List<CollectionItem*> fContainer;
public:
Collection(void) {}
virtual ~Collection() {}
virtual const ICollectionItem* At(const int idx); // Casting GetAt result
virtual const TCollectionItem& GetAt(const int idx) const
virtual ListIterator<TCollectionItem> >* GetIterator(void) const;
virtual ListIterator<ICollectionItem> >* Iterator(void) const; // Weak point
}
Example usage:
class IBaseItem
{
public:
virtual int Number() = 0;
{
class BaseItem
: public IBaseItem
{
public:
virtual int Number();
void SetNumber(int value);
}
class IBase
: public virtual ICollection<IBaseItem>
{
public:
virtual IBaseItem* ItemByName(String name) = 0;
virtual ~IBase() {}
}
class Base
: public Collection<BaseItem, IBaseItem>,
public IBase
{
public:
BaseItem* GetItemByName(String name);
virtual IBaseItem* ItemByName(String name);
}
Weak points:
First is at using virtual inheritance ... lots written about it, not much to talk about, or is it?
Unable to access Iterator using ICollection interface. See ListIterator function, only first one can be implemented, the second one would require some kind of new List of IBaseItem. I decided to live with that and just use for loop.
Even tho I somehow managed to get what I wanted (With wrapping and casting), I would still like to hear an second opinion. I don't like using virtual inheritance, specially in such delicate situations - using Collections for application Base creation.
I can not see any other solution than calling some Collection method in Base implementation of IBase virtual methods.
class Base : public Collection<BaseItem>, public IBase
{
virtual void B()
{
A();
}
}
You say, and I quote:
I want to call Collection functions using IBase pointer
I really don't see what is to be done here besides dynamic_cast. It does exactly what you want it to do.
void fun(IBase * base) {
auto * coll = dynamic_cast<Collection<BaseItem>*>(base);
if (coll) {
coll->A();
}
}
Your Collection class must have a virtual destructor.
You can, of course, offer a templated version, if you'd need different baseitems in different, scenarios for some reasons. This has bad code smell and I think your architecture is bad at this point, but oh well.
template <typename T> void fun(IBase * base) {
auto * coll = dynamic_cast<Collection<T>*>(base);
if (coll) {
coll->A();
}
}
void test(IBase * p) {
fun<BaseItem5>(p);
}
If you have some other specific scenario in mind, please edit your question to say what you mean.
Hmm...So you wanna to reuse the Collection class's utility functions, and you want to design a class which will implement an interface defined by IBase. As you mentioned above,"wrapping all the functions in Base class" is a way to offer Collection functions.
(1) Via inheritance,derived class has a good knowledge of Collection
class Derived:public Collection<DerivedType>,public IBase{};
or
template <typename T>
class Derived:public Collection<T>,public IBase{};
(2) Via inheritance,derived class knows little about Collection,but through IBase
class IBase : public Collection<BaseItem>{};
class Derived:public IBase{};
By (1),If you want to call Collection functions using IBase pointer,you have to wrap the functions.
By (2), any Derived instance is " a kind of " IBase which is "a kind of " Collection. So you can use IBase pointer to call Collection functions.
So,the key point is that the objects pointed by the IBase pointer should have the method you want to call.Wrap it or inherit it. I can not see any other solution than these two ways.
Edit: the idea is refined based on your example:
Here is an idea:
//generic interface can be kept as it is
template <class ICollectionItem>
class ICollection
{
public:
virtual const ICollectionItem* At(const int idx) = 0;
};
class Empty
{
};
template <class CollectionItem , class BaseClass = Empty>
class GenericCollection
: public BaseClass
{
public:
const CollectionItem* At(const int idx);
// At and ItemByName are standard functions for a collection
CollectionItem* ItemByName(String name);
//note that here nothing has to be declared as virtual
};
//example usage:
class IBase
: public virtual ICollection<IBaseItem>
{
public:
virtual IBaseItem* ItemByName(String name) = 0;
virtual ~IBase() {}
};
class Base
: public GenericCollection<BaseItem, IBase >
{
public:
//nothing to be implemented here, all functions are implemented in GenericCollection and defined as virtual in IBase
//The definition of the functions has to be the same:
};
In collection you can implement whatever and in the interface you can define what ever you want to be virtual from your collection. The only thing is that you need to have some standard in naming convention for functions.
Hope this helps,
Raxvan.
From your comments in another answer, it seems you want a collection of interfaces, and an implementation of this interface. The simplest I can advise you is the following:
template<typename T>
class ICollection
{
public:
virtual iterator<T>* begin() const = 0;
};
template<typename T, typename TBase>
class Collection : public ICollection<TBase>
{
public:
iterator_impl<T>* begin() const { return whatever; }
};
Example:
class IItem {};
class Item : public IItem {};
class Base : public Collection<Item, IItem> {};
old answer:
Is there any way of offering Collection functions via IBase interface without wrapping all the functions in Base class ?
If I understood your problem, you want to use it like this:
void myfunc()
{
// ...
IBase* obj = ...;
obj->A();
obj->B();
}
I think here is a misunderstanding here: if you want A() to be callable from an IBase, then you have to add it to Ibase declaration.
If you want to use the Collection functions on an object, then you should cast this object to a Collection, via dynamic_cast for example.
Furthermore, if you have such a funcion:
void fun(IBase* base) { /* ... */ }
you cannot cast to a Collection*, since there are no relationship between these two classes, unless you have another way to be sure base is a Collection:
void fun(IBase* base)
{
if(base && base->isABaseItemCollection())
{
// Valid, since the real type was checked before
Collection* collection = (Collection*)base;
// ...
}
}
On a side note: you can generate bases almost automatically:
template
class Base : public Collection, public U {};
typedef Base BaseCollection;
According to comment/chat:
You have something like:
class IAnimal { /*...*/ };
class Cat : public IAnimal { /*...*/ };
class Dog : public IAnimal { /*...*/ };
class Cats
{
std::vector<Cat*> cats;
public:
Cat* at(size_t index) { return cats[index]; }
/*...*/
};
class Dogs
{
std::vector<Dog*> dogs;
public:
Dog* at(size_t index) { return dogs[index]; }
/*...*/
};
And you want to factorize some code using something like
class IAnimals
{
public:
std::vector<IAnimals*> animals; // or getter/setter which works with IAnimals.
/* some common factorized code */
};
// And so
class Cats : public IAnimals { /**/ };
class Dogs : public IAnimals { /**/ };
I propose, instead of creating class IAnimals, to use template functions as:
template <typename TAnimals>
void foo(TAnimals& animals)
{
Ianimals* animal = animals.at(42);
// ...
animal->eat(food);
// ...
}
You have to give compatible "interface" (names) to the type used in template.
Maybe you could have an operator() in IBase that would be delegated to Base?
class CollectionBase {};
template <class Item> class Collection: public CollectionBase {};
class IBase
{
public:
virtual CollectionBase* operator()() = 0;
};
class Base : public Collection<BaseItem>, public IBase
{
public:
virtual Collection<BaseItem>* operator()() { return this; }
};