C++ template specify type by Enum - c++

I'm facing a problem :
I want to create a function which calls a specific template type constructor depending on a enum that the function will receive. By that i mean :
typedef ____ (Class<whatever>::*tabType)(int flag);
template<typename T>
static Class* Class<t>::createClassInstance(enum precision)
{
static const ___ createTab[] = {
Class<int>,
Class<double>
}
return (new createTab[precision](1));
}

There are a number of ways of achieving this sort of thing, but it sounds like you want to create an array (or map) of factory methods (one for each class), indexed by the enum variable. Each one calls the relevant constructor, and returns a new object of that type.
Of course, for this to make any sense, all of the classes must derive from a common base.

If the enum value is dynamic as a function argument, you'll have to use either a dispatch table or switch/if-else. Notice that your pseudo code does not clearly explain the requirement. Say, what exactly the createInstance function you wish to define and how is it going to be called?

I would say, just construct a std::map that maps the enum to a factory function (boost::function<>). Then you just add one entry for each type that you want, with its corresponding enum. To actually construct the factory functions. You can either have some static Create() function for each class and store a function pointer. Or, you can use Boost.Lambda constructor/destructor functors. Or, you can use Boost.Bind to construct functors that wrap a factory function that requires some number of parameters. Here is an example:
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/lambda/construct.hpp>
#include <map>
struct Base { };
struct Derived1 : public Base { };
struct Derived2 : public Base {
static Base* Create() { return new Derived2; };
};
struct Derived3 : public Base {
int value;
Derived3(int aValue) : value(aValue) { };
static Base* Create(int aValue) { return new Derived3(aValue); };
};
enum DerivedCreate { ClassDerived1, ClassDerived2, ClassDerived3 };
int main() {
std::map< DerivedCreate, boost::function< Base*() > constructor_map;
constructor_map[ClassDerived1] = boost::lambda::new_ptr<Derived1>();
constructor_map[ClassDerived2] = &Derived2::Create;
constructor_map[ClassDerived3] = boost::bind(&Derived3::Create, 42);
//now you can call any constructor as so:
Base* ptr = constructor_map[ClassDerived2]();
};
I might have made some slight syntax mistakes, but basically you should be able make the above work. Also, the fact that you have several class templates plays no role, once they are instantiated to a concrete class (like Class<int> or Class<double>) they are just like any other class, and the above idea should remain valid.

Extending your example, something like the following works:
enum Prec {INT, DOUBLE};
struct Base
{
virtual ~Base () = 0 {}
};
template<typename T> struct Class : public Base
{
static Base* create (int flag) {return new Class<T> (flag);}
Class (int flag) {}
};
typedef Base* (*Creator) (int flag);
Base* createClassInstance (Prec prec)
{
static const Creator createTab[] = {
Class<int>::create,
Class<double>::create
};
return createTab[prec] (1);
}
int main (int argc, char* argv[])
{
Base* c = createClassInstance (DOUBLE);
return 0;
}

Related

How would you design a function that attaches children of a Component class to an Object class if the components can hold different data?

In my program, I have an Object class to which we can attach components that all derive from a base Component class. Since a component can have data that are initialized through it's constructor, when we call Object::addComponent() we need to pass the data for this particular component
#include <vector>
class Component;
class Object
{
public:
Object() {}
/* The challenge comes from implementing this function, the signature will change later in this post
and ideally it would return the added component */
void addComponent();
private:
std::vector<Component*> m_components;
};
class Component
{
public:
Component(Object* owner) : m_owner(owner) {}
// Note the pure virtual destructor, meaning Component is meant to be derived
virtual ~Component() = 0;
private:
Object* m_owner;
};
Here are two Component derived classes for our example
// This component holds an int
class ComponentDerivedA : public Component
{
public:
ComponentDerivedA(Object* owner, int data) : Component(owner), m_data(data) {}
virtual ~ComponentDerivedA() override {}
private:
int m_data;
};
// This component holds a string
class ComponentDerivedB : public Component
{
public:
ComponentDerivedB(Object* owner, char* message) : Component(owner), m_message(message) {}
virtual ~ComponentDerivedB() override {}
private:
char* message;
};
The only solution I came for to implement the addComponent() function the way I want to is to create an enum and a struct:
enum class ComponentType { A, B };
struct ComponentInfo
{
ComponentType type;
int data;
char* message
};
So we change the signature for Object::addComponent() to the following
void* Object::addComponent(const ComponentInfo& info);
And here is a possible implementation
void* Object::addComponent(const ComponentInfo& info)
{
switch(info.type)
{
case A:
{
// We ignore cleaning up for this example but it would go in the destructor
ComponentDerivedA* a = new ComponentDerivedA(this, info.data);
m_components.push_back(a);
return a;
}
break;
case B:
{
// We ignore cleaning up for this example but it would go in the destructor
ComponentDerivedB* b = new ComponentDerivedB(this, info.message);
m_components.push_back(b);
return b;
}
break;
}
}
And here is how we would use it
int main()
{
Object obj;
ComponentInfo info{0};
info.type = ComponentType::A;
info.data = 5;
obj.addComponent(info);
/*
If I wanted to use the component right after I would have to do:
reinterpret_cast<ComponentDerivedA>(obj.addComponent(info)).doSomething();
*/
return 0;
}
This solution works okay but anytime you want to call addComponent() you have to declare a struct before, the only benefit is if you add multiple components you can reuse the same struct and just change the data between each call, also is if you add a new component type you have to expand the enum and the function, if you have many component the switch can become very large but the code inside it remains pretty repetitive and simple. And the final flaw is that it's up to the caller to cast the return value as the component type.
Here is a possible solution.
Note the use of std::unique_ptr instead of regular c-pointers.
#include <memory>
#include <vector>
struct Component{};
class Object {
public:
Object() {}
template <typename TDerivedComponent, typename... TArgs>
TDerivedComponent * addComponent(TArgs&&... args){
auto ptr = std::make_unique<TDerivedComponent>
(std::forward<TArgs>(args)...);
TDerivedComponent * result = ptr.get();
m_components.push_back(std::move(ptr));
return result;
}
private:
std::vector<std::unique_ptr<Component> > m_components;
};
struct ComponentA : public Component {
ComponentA(int x, int y){}
};
struct ComponentB : public Component {};
struct Invalid{};
int main(){
Object obj;
ComponentA * a = obj.addComponent<ComponentA>(1, 2);
ComponentB * b = obj.addComponent<ComponentB>();
// obj.addComponent<Invalid>(); -> error!
}
You actually can store a derived object into a baseclass object pointer which u already have declared as in the vector.
To make your derived objects also call the correct methods you have to declare the method as virtual inside the base class.
your addComponent() function can then take the pointer of the baseClass
addComponent(Component * c)
with that signature it can also take derived object pointers.
You should read about static vs dynamic binding in C++.

C++ Errors declaring Interface with return template

I have a base interface, declaration like this - IBaseTest.h:
#pragma once
template <class T1>
class IBaseTest
{
public:
virtual ~IBaseTest();
virtual T1 DoSomething() = 0;
};
And two children who overrides DoSomething() CBaseTest1 claass in - BaseTest1.h:
#pragma once
#include "IBaseTest.h"
class CBaseTest1: public IBaseTest<int>
{
public:
virtual int DoSomething();
};
BaseTest1.cpp:
#include "BaseTest1.h"
int CBaseTest1::DoSomething()
{
return -1;
}
And CBaseTest2 in - BaseTest2.h
#pragma once
#include "IBaseTest.h"
class CBaseTest2: public IBaseTest<long long>
{
public:
virtual long long DoSomething();
};
BaseTest2.cpp:
#include "BaseTest2.h"
long long CBaseTest2::DoSomething()
{
return -2;
}
So CBaseTest1::DoSomething() overrides return type to int, and CBaseTest2::DoSomething() to long long. Now, i want to use a pointer to the base interface, to work with those classes, and there i have the problem:
#include "IBaseTest.h"
#include "BaseTest1.h"
#include "BaseTest2.h"
int _tmain(int argc, _TCHAR* argv[])
{
IBaseTest<T1> * pBase = NULL;
pBase = new CBaseTest1();
cout << pBase->DoSomething() << endl;
pBase = new CBaseTest2();
cout << pBase->DoSomething() << endl;
getchar();
return 0;
}
The problem is i cannot declare IBaseTest<T1> * pBase = NULL; T1 is undefined. If declare the template before _tmain like this:
template <class T1>
int _tmain(int argc, _TCHAR* argv[])
{
...
}
I get: error C2988: unrecognizable template declaration/definition
So what do i put here instead of T1?
IBaseTest<??> * pBase = NULL;
The problem is that T1 parameter needs to be known when you instantiate an object of the template class IBaseTest. Technically, IBaseTest<int> and IBaseTest<long long> are two different types without a common base and C++ does not allow you to declare a variable IBaseTest<T1> pBase = NULL; where T1 is determined at runtime. What you are trying to achieve is something that would be possible in a dynamically typed language, but not in C++ because it is statically typed.
However, if you know the expected return type of DoSomething whenever you call that method, you can sort of make your example to work. First, you need to introduce a common base class that is not a template:
#include <typeinfo>
#include <typeindex>
#include <assert.h>
class IDynamicBase {
public:
virtual std::type_index type() const = 0;
virtual void doSomethingVoid(void* output) = 0;
template <typename T>
T doSomething() {
assert(type() == typeid(T));
T result;
doSomethingVoid(&result);
return result;
}
virtual ~IDynamicBase() {}
};
Note that it has a template method called doSomething that takes a type parameter for the return value. This is the method that we will call later.
Now, modify your previous IBaseTest to extend IDynamicBase:
template <class T1>
class IBaseTest : public IDynamicBase
{
public:
std::type_index type() const {return typeid(T1);}
void doSomethingVoid(void* output) {
*(reinterpret_cast<T1*>(output)) = DoSomething();
}
virtual T1 DoSomething() = 0;
virtual ~IBaseTest() {}
};
You don't need to change CBaseTest1 or CBaseTest2.
Finally, you can now write the code in your main function like this:
IDynamicBase* pBase = nullptr;
pBase = new CBaseTest1();
std::cout << pBase->doSomething<int>() << std::endl;
pBase = new CBaseTest2();
std::cout << pBase->doSomething<long long>() << std::endl;
Note that instead of calling pBase->DoSomething(), we now call pBase->doSomething<T>() where T is a type that must be known statically where we call the method and we provide that type at the call site, e.g. pBase->doSomething<int>().
The language does not allows to do directly what you are trying to do. At that point, you should ask yourself if that is the right solution for the problem.
The first approach that might work well assuming that you don't have too much different operations to do for each type would be to simply do the action in the function itself instead of returning type that are not related through inheritance.
class IBaseTest
{
public:
virtual void OutputTo(std::ostream &os) = 0;
};
class CBaseTest1
{
public:
virtual void OutputTo(std::ostream &os) override;
private:
int DoSomething();
};
void CBaseTest1OutputTo(std::ostream &os)
{
os << DoSomething() << std::endl;
}
If you have only a few types but a lot of operation, you might use the visitor pattern instead.
If you mainly have operation that depends on type, you could use:
class IVisitor
{
public:
virtual void Visit(int value) = 0;
virtual void Visit(long value) = 0;
};
Otherwise, use that which is more general
class IVisitor
{
public:
virtual void Visit (CBaseTest1 &test1) = 0;
virtual void Visit (CBaseTest2 &test2) = 0;
};
Then in your classes add an apply function
class IBaseTest
{
public:
virtual void Apply(IVisitor &visitor) = 0;
};
In each derived class, you implement the Apply function:
void CBaseTest1 : public IBaseTest
{
virtual void Apply(IVisitor &visitor) override
{
visitor.Visit(this->DoSomething()); // If you use first IVisitor definition
visitor.Visit(*this); // If you use second definition
};
And for creation purpose, you could have a factory that return the appropriate class from a type tag if you need to create those class from say a file…
One example assuming you want a new object each time:
enum class TypeTag { Integer = 1, LongInteger = 2 };
std::unique_ptr<IBaseTest> MakeObjectForTypeTag(TypeTag typeTag)
{
switch (typeTag)
{
case TypeTag::Integer : return new CBaseTest1();
case TypeTag::LongInteger : return new CBaseTest2();
}
}
So the only time you would do a switch statement is when you are creating an object… You could also use a map or even an array for that...
The right approach depends on your actual problem.
How many CBaseClass* do you have?
Do you expect to add other classes? Often?
How many operations similar to DoSomething() do you have?
How many actions that works on the result of DoSomething do you have?
Do you expect to add other actions? Often?
By responding to those questions, it will be much easier to take the right decision. If the action are stables (and you only have a few one), then specific virtual functions like OutputToabove is more appropriate. But if you have dozen of operation but don't expect much changes to ITestBase class hierarchy, then visitor solution is more appropriate.
And the reason why a given solution is more appropriate in a given context is mainly the maintenance effort when adding classes or actions in the future. You typically want that the most frequent change (adding a class or an action) require les changes everywhere in the code.

Overwrite Base Class Member with New Type

I'm trying to use C++ to emulate something like dynamic typing. I'm approaching the problem with inherited classes. For example, a function could be defined as
BaseClass* myFunction(int what) {
if (what == 1) {
return new DerivedClass1();
} else if (what == 2) {
return new DerivedClass2();
}
}
The base class and each derived class would have the same members, but of different types. For example, BaseClass may have int xyz = 0 (denoting nothing), DerivedClass1 might have double xyz = 123.456, and DerivedClass2 might have bool xyz = true. Then, I could create functions that returned one type but in reality returned several different types. The problem is, when ere I try to do this, I always access the base class's version of xyz. I've tried using pointers (void* for the base, and "correct" ones for the derived classes), but then every time I want to access the member, I have to do something like *(double*)(obj->xyz) which ends up being very messy and unreadable.
Here's an outline of my code:
#include <iostream>
using std::cout;
using std::endl;
class Foo {
public:
Foo() {};
void* member;
};
class Bar : public Foo {
public:
Bar() {
member = new double(123.456); // Make member a double
};
};
int main(int argc, char* args[]) {
Foo* obj = new Bar;
cout << *(double*)(obj->member);
return 0;
};
I guess what I'm trying to ask is, is this "good" coding practice? If not, is there a different approach to functions that return multiple types or accept multiple types?
That is not actually the way to do it.
There are two typical ways to implement something akin to dynamic typing in C++:
the Object-Oriented way: a class hierarchy and the Visitor pattern
the Functional-Programming way: a tagged union
The latter is rather simple using boost::variant, the former is well documented on the web. I would personally recommend boost::variant to start with.
If you want to go down the full dynamic typing road, then things get trickier. In dynamic typing, an object is generally represented as a dictionary containing both other objects and functions, and a function takes a list/dictionary of objects and returns a list/dictionary of objects. Modelling it in C++ is feasible, but it'll be wordy...
How is an object represented in a dynamically typed language ?
The more generic representation is for the language to represent an object as both a set of values (usually named) and a set of methods (named as well). A simplified representation looks like:
struct Object {
using ObjectPtr = std::shared_ptr<Object>;
using ObjectList = std::vector<ObjectPtr>;
using Method = std::function<ObjectList(ObjectList const&)>;
std::map<std::string, ObjectPtr> values;
std::map<std::string, Method> methods;
};
If we take Python as an example, we realize we are missing a couple things:
We cannot implement getattr for example, because ObjectPtr is a different type from Method
This is a recursive implementation, but without the basis: we are lacking innate types (typically Bool, Integer, String, ...)
Dealing with the first issue is relatively easy, we transform our object to be able to become callable:
class Object {
public:
using ObjectPtr = std::shared_ptr<Object>;
using ObjectList = std::vector<ObjectPtr>;
using Method = std::function<ObjectList(ObjectList const&)>;
virtual ~Object() {}
//
// Attributes
//
virtual bool hasattr(std::string const& name) {
throw std::runtime_error("hasattr not implemented");
}
virtual ObjectPtr getattr(std::string const&) {
throw std::runtime_error("gettattr not implemented");
}
virtual void setattr(std::string const&, ObjectPtr) {
throw std::runtime_error("settattr not implemented");
}
//
// Callable
//
virtual ObjectList call(ObjectList const&) {
throw std::runtime_error("call not implemented");
}
virtual void setcall(Method) {
throw std::runtime_error("setcall not implemented");
}
}; // class Object
class GenericObject: public Object {
public:
//
// Attributes
//
virtual bool hasattr(std::string const& name) override {
return values.count(name) > 0;
}
virtual ObjectPtr getattr(std::string const& name) override {
auto const it = values.find(name);
if (it == values.end) {
throw std::runtime_error("Unknown attribute");
}
return it->second;
}
virtual void setattr(std::string const& name, ObjectPtr object) override {
values[name] = std::move(object);
}
//
// Callable
//
virtual ObjectList call(ObjectList const& arguments) override {
if (not method) { throw std::runtime_error("call not implemented"); }
return method(arguments);
}
virtual void setcall(Method m) {
method = std::move(m);
}
private:
std::map<std::string, ObjectPtr> values;
Method method;
}; // class GenericObject
And dealing with the second issue requires seeding the recursion:
class BoolObject final: public Object {
public:
static BoolObject const True = BoolObject{true};
static BoolObject const False = BoolObject{false};
bool value;
}; // class BoolObject
class IntegerObject final: public Object {
public:
int value;
}; // class IntegerObject
class StringObject final: public Object {
public:
std::string value;
}; // class StringObject
And now you need to add capabilities, such as value comparison.
You can try the following design:
#include <iostream>
using std::cout;
using std::endl;
template<typename T>
class Foo {
public:
Foo() {};
virtual T& member() = 0;
};
class Bar : public Foo<double> {
public:
Bar() : member_(123.456) {
};
virtual double& member() { return member_; }
private:
double member_;
};
int main(int argc, char* args[]) {
Foo<double>* obj = new Bar;
cout << obj->member();
return 0;
};
But as a consequence the Foo class already needs to be specialized and isn't a container for any type anymore.
Other ways to do so, are e.g. using a boost::any in the base class
If you need a dynamic solution you should stick to using void* and size or boost::any. Also you need to pass around some type information as integer code or string so that you can decode the actual type of the content.
See also property design pattern.
For example, you can have a look at zeromq socket options https://github.com/zeromq/libzmq/blob/master/src/options.cpp

minimal reflection in C++

I want to create a class factory and I would like to use reflection for that. I just need to
create a object with given string and invoke only few known methods.
How i can do that?
You will have to roll your own. Usually you have a map of strings to object creation functions.
You will need something like the follwing:
class thing {...};
/*
class thing_A : public thing {...};
class thing_B : public thing {...};
class thing_C : public thing {...};
*/
std::shared_ptr<thing> create_thing_A();
std::shared_ptr<thing> create_thing_C();
std::shared_ptr<thing> create_thing_D();
namespace {
typedef std::shared_ptr<thing> (*create_func)();
typedef std::map<std::string,create_func> creation_map;
typedef creation_map::value_type creation_map_entry;
const creation_map_entry creation_map_entries[] = { {"A", create_thing_A}
, {"B", create_thing_B}
, {"C", create_thing_C} };
const creation_map creation_funcs(
creation_map_entries,
creation_map_entries + sizeof(creation_map_entries)
/ sizeof(creation_map_entries[0] );
}
std::shared_ptr<thing> create_thing(const std::string& type)
{
const creation_ma::const_iterator it = creation_map.find(type);
if( it == creation_map.end() ) {
throw "Dooh!"; // or return NULL or whatever suits you
}
return it->second();
}
There are other ways to do this (like having a map of strings to objects from which to clone), but I think they all boil down to having a map of strings to something related to the specific types.
There is no reflection in C++, directly supported by the standard.
However C++ is sufficiently low-level that you can implement some minimal support for reflection to complete the task at hand.
For the simple task of creating a Factory, you usually use the Prototype approach:
class Base
{
public:
virtual Base* clone() const = 0;
virtual ~Base();
};
class Factory
{
public:
std::unique_ptr<Base> get(std::string const& name);
void set(std::string const& name, std::unique_ptr<Base> b);
private:
boost::ptr_map<std::string,Base> mExemplars;
};
Of course, those "known methods" that you are speaking about should be defined within the Base class, which acts as an interface.
There is no reflection in C++, so you should restate your question trying to explain what are the requirements that you would have fulfilled with the reflection part of it.
Depending on your actual constraints and requirements, there are a few things that you can do. The first approach that I would take would be creating an abstract factory where concrete factories can register and provide a simple interface:
class Base {}; // shared base by all created objects
class ConcreteFactoryBase {
public:
virtual ~ConcreteFactoryBase() {}
virtual Base* create() const = 0; // actual construction
virtual std::string id() const = 0; // id of the types returned
};
class AbstractFactory
{
typedef std::map<std::string, ConcreteFactory* > factory_map_t;
public:
void registerFactory( ConcreteFactoryBase* factory ) {
factories[ factory->id() ] = factory;
}
Base* create( std::string const & id ) const {
factory_map_t::const_iterator it = factories.find( id );
if ( it == factories.end() ) {
return 0; // or throw, or whatever makes sense in your case
}
return (*it)->create();
}
~AbstractFactory(); // ensure that the concrete factories are deleted
private:
std::map<ConcreteFactoryBase*> factories;
};
The actual concrete factories can be implemented manually but they can probably be templated, unless the constructors for the different types require different arguments:
template <typename T>
class ConcreteFactory : public ConcreteFactoryBase {
public:
ConcreteFactory( std::string const & id ) : myid(id) {}
virtual Base* create() const {
return new T;
}
virtual std::string id() const {
return myid;
}
private:
std::string myid;
};
class Test : public Base {};
int main() {
AbstracFactory factory;
factory.register_factory( new ConcreteFactory<Test>("Test") );
}
Optionally you could adapt the signatures so that you can pass arguments to the constructor through the different layers.
Then again, by knowing the actual constraints some other approaches might be better. The clone() approach suggested elsewhere is good (either by actually cloning or by creating an empty object of the same type). That is basically blending the factory with the objects themselves so that each object is a factory of objects of the same type. I don't quite like mixing those two responsabilities but it might be one of the simplest approaches with less code to write.
You could use typeid & templates to implement the factory so you won't need strings at all.
#include <string>
#include <map>
#include <typeinfo>
//***** Base *****
class Base
{
public:
virtual ~Base(){} //needs to be virtual to make typeid work
};
//***** C1 *****
class C1 : public Base
{};
//***** Factory *****
class Factory
{
public:
template <class T>
Base& get();
private:
typedef std::map<std::string, Base> BaseMap;
BaseMap m_Instances;
};
template <class T>
Base& Factory::get()
{
BaseMap::const_iterator i = m_Instances.find(typeid(T).name());
if(i == m_Instances.end()) {
m_Instances[typeid(T).name()] = T();
}
return m_Instances[typeid(T).name()];
}
//***** main *****
int main(int argc, char *argv[])
{
Factory f;
Base& c1 = f.get<C1>();
return 0;
}

How can I use covariant return types with smart pointers?

I have code like this:
class RetInterface {...}
class Ret1: public RetInterface {...}
class AInterface
{
public:
virtual boost::shared_ptr<RetInterface> get_r() const = 0;
...
};
class A1: public AInterface
{
public:
boost::shared_ptr<Ret1> get_r() const {...}
...
};
This code does not compile.
In visual studio it raises
C2555: overriding virtual function return type differs and is not
covariant
If I do not use boost::shared_ptr but return raw pointers, the code compiles (I understand this is due to covariant return types in C++). I can see the problem is because boost::shared_ptr of Ret1 is not derived from boost::shared_ptr of RetInterface. But I want to return boost::shared_ptr of Ret1 for use in other classes, else I must cast the returned value after the return.
Am I doing something wrong?
If not, why is the language like this - it should be extensible to handle conversion between smart pointers in this scenario? Is there a desirable workaround?
Firstly, this is indeed how it works in C++: the return type of a virtual function in a derived class must be the same as in the base class. There is the special exception that a function that returns a reference/pointer to some class X can be overridden by a function that returns a reference/pointer to a class that derives from X, but as you note this doesn't allow for smart pointers (such as shared_ptr), just for plain pointers.
If your interface RetInterface is sufficiently comprehensive, then you won't need to know the actual returned type in the calling code. In general it doesn't make sense anyway: the reason get_r is a virtual function in the first place is because you will be calling it through a pointer or reference to the base class AInterface, in which case you can't know what type the derived class would return. If you are calling this with an actual A1 reference, you can just create a separate get_r1 function in A1 that does what you need.
class A1: public AInterface
{
public:
boost::shared_ptr<RetInterface> get_r() const
{
return get_r1();
}
boost::shared_ptr<Ret1> get_r1() const {...}
...
};
Alternatively, you can use the visitor pattern or something like my Dynamic Double Dispatch technique to pass a callback in to the returned object which can then invoke the callback with the correct type.
There is a neat solution posted in this blog post (from Raoul Borges)
An excerpt of the bit prior to adding support for mulitple inheritance and abstract methods is:
template <typename Derived, typename Base>
class clone_inherit<Derived, Base> : public Base
{
public:
std::unique_ptr<Derived> clone() const
{
return std::unique_ptr<Derived>(static_cast<Derived *>(this->clone_impl()));
}
private:
virtual clone_inherit * clone_impl() const override
{
return new Derived(*this);
}
};
class concrete: public clone_inherit<concrete, cloneable>
{
};
int main()
{
std::unique_ptr<concrete> c = std::make_unique<concrete>();
std::unique_ptr<concrete> cc = c->clone();
cloneable * p = c.get();
std::unique_ptr<clonable> pp = p->clone();
}
I would encourage reading the full article. Its simply written and well explained.
You can't change return types (for non-pointer, non-reference return types) when overloading methods in C++. A1::get_r must return a boost::shared_ptr<RetInterface>.
Anthony Williams has a nice comprehensive answer.
What about this solution:
template<typename Derived, typename Base>
class SharedCovariant : public shared_ptr<Base>
{
public:
typedef Base BaseOf;
SharedCovariant(shared_ptr<Base> & container) :
shared_ptr<Base>(container)
{
}
shared_ptr<Derived> operator ->()
{
return boost::dynamic_pointer_cast<Derived>(*this);
}
};
e.g:
struct A {};
struct B : A {};
struct Test
{
shared_ptr<A> get() {return a_; }
shared_ptr<A> a_;
};
typedef SharedCovariant<B,A> SharedBFromA;
struct TestDerived : Test
{
SharedBFromA get() { return a_; }
};
Here is my attempt :
template<class T>
class Child : public T
{
public:
typedef T Parent;
};
template<typename _T>
class has_parent
{
private:
typedef char One;
typedef struct { char array[2]; } Two;
template<typename _C>
static One test(typename _C::Parent *);
template<typename _C>
static Two test(...);
public:
enum { value = (sizeof(test<_T>(nullptr)) == sizeof(One)) };
};
class A
{
public :
virtual void print() = 0;
};
class B : public Child<A>
{
public:
void print() override
{
printf("toto \n");
}
};
template<class T, bool hasParent = has_parent<T>::value>
class ICovariantSharedPtr;
template<class T>
class ICovariantSharedPtr<T, true> : public ICovariantSharedPtr<typename T::Parent>
{
public:
T * get() override = 0;
};
template<class T>
class ICovariantSharedPtr<T, false>
{
public:
virtual T * get() = 0;
};
template<class T>
class CovariantSharedPtr : public ICovariantSharedPtr<T>
{
public:
CovariantSharedPtr(){}
CovariantSharedPtr(std::shared_ptr<T> a_ptr) : m_ptr(std::move(a_ptr)){}
T * get() final
{
return m_ptr.get();
}
private:
std::shared_ptr<T> m_ptr;
};
And a little example :
class UseA
{
public:
virtual ICovariantSharedPtr<A> & GetPtr() = 0;
};
class UseB : public UseA
{
public:
CovariantSharedPtr<B> & GetPtr() final
{
return m_ptrB;
}
private:
CovariantSharedPtr<B> m_ptrB = std::make_shared<B>();
};
int _tmain(int argc, _TCHAR* argv[])
{
UseB b;
UseA & a = b;
a.GetPtr().get()->print();
}
Explanations :
This solution implies meta-progamming and to modify the classes used in covariant smart pointers.
The simple template struct Child is here to bind the type Parent and inheritance. Any class inheriting from Child<T> will inherit from T and define T as Parent. The classes used in covariant smart pointers needs this type to be defined.
The class has_parent is used to detect at compile time if a class defines the type Parent or not. This part is not mine, I used the same code as to detect if a method exists (see here)
As we want covariance with smart pointers, we want our smart pointers to mimic the existing class architecture. It's easier to explain how it works in the example.
When a CovariantSharedPtr<B> is defined, it inherits from ICovariantSharedPtr<B>, which is interpreted as ICovariantSharedPtr<B, has_parent<B>::value>. As B inherits from Child<A>, has_parent<B>::value is true, so ICovariantSharedPtr<B> is ICovariantSharedPtr<B, true> and inherits from ICovariantSharedPtr<B::Parent> which is ICovariantSharedPtr<A>. As A has no Parent defined, has_parent<A>::value is false, ICovariantSharedPtr<A> is ICovariantSharedPtr<A, false> and inherits from nothing.
The main point is as Binherits from A, we have ICovariantSharedPtr<B>inheriting from ICovariantSharedPtr<A>. So any method returning a pointer or a reference on ICovariantSharedPtr<A> can be overloaded by a method returning the same on ICovariantSharedPtr<B>.
Mr Fooz answered part 1 of your question. Part 2, it works this way because the compiler doesn't know if it will be calling AInterface::get_r or A1::get_r at compile time - it needs to know what return value it's going to get, so it insists on both methods returning the same type. This is part of the C++ specification.
For the workaround, if A1::get_r returns a pointer to RetInterface, the virtual methods in RetInterface will still work as expected, and the proper object will be deleted when the pointer is destroyed. There's no need for different return types.
maybe you could use an out parameter to get around "covariance with returned boost shared_ptrs.
void get_r_to(boost::shared_ptr<RetInterface>& ) ...
since I suspect a caller can drop in a more refined shared_ptr type as argument.