Conversion between C++ vector of base and derived classes - c++

Please have a look at the following code, you can compile it as a single .cpp file but you should imagine base library code in a separate package:
#include <iostream>
#include <memory>
#include <vector>
// Start of classes defined in a base library shared by many projects
class BaseObject
{
public:
BaseObject() : value(0) {}
BaseObject(int val) : value(val) {}
protected:
int value;
};
class BaseObjectHandler
{
public:
void setVector(std::unique_ptr<std::vector<BaseObject>>&& v)
{
vec = std::move(v);
}
protected:
std::unique_ptr<std::vector<BaseObject>> vec;
};
// End of classes defined in a base library shared by many projects
// Start of specific implementation for project A
class SpecificObject : public BaseObject
{
public:
SpecificObject() : BaseObject(0) {}
};
class SpecificObjectHandler : public BaseObjectHandler
{
public:
void doSomethingOnVector()
{
// Do something on vector
}
};
int main()
{
SpecificObjectHandler handler;
handler.setVector(std::make_unique<std::vector<SpecificObject>>());
handler.doSomethingOnVector();
exit(0);
}
// End of specific implementation for project A
BaseObjectHandler can share some common operations to its derived handlers, but knows nothing about SpecificObject, because it resides in a separate package base library.
In turn SpecificObjectHandler resides in project A package, knows about SpecificObject of course, and needs the above mentioned common operations that do not act on SpecificObject instances but rely only on BaseObject.
The code obviously does not compile because of error conversion from std::vector<SpecificObject> to std::vector<BaseObject>.
Is there a simple and elegant C++ 14 way to solve this issue? Or do you suggest a completely different pattern for this problem?
I found some answers to similar problems but I need more specific clarification.
Thanks.

Assuming you can edit the base library code, you could define BaseObjectHandler as a template class
// base_class_library.hpp
template<typename ObjectType>
class BaseObjectHandler
{
public:
void setVector(std::unique_ptr<std::vector<ObjectType>>&& v)
{
vec = std::move(v);
}
protected:
std::unique_ptr<std::vector<ObjectType>> vec;
};
and inherit class SpecificObjectHandler : public BaseObjectHandler<SpecificObject>. Now SpecificObjectHandler has pointer to vector of SpecificObjects and your code would compile.
Of course it may lead to conflicts with other uses of the base library, but whenever you need the old (your) version of BaseObjectHandler you can declare it as BaseObjectHandler<BaseObject>. As a price, you would loose a possibility to upcast SpecificObjectHandler into generic BaseObjectHandler, but maybe that is not important for you.

Related

Why can't I instantiate a reference to a base class at the same time as a pointer to a derived class?

The simplest example of my question can be seen in the following code snippet:
class Handle : public IHandle_<Handle>{
public:
Handle(std::unique_ptr<Derived> aDerived)
: derived(std::move(aDerived)),
base(*aDerived) {};
std::unique_ptr<Derived> derived;
Base& base;
};
Here, you can see that the Handle class is essentially a wrapper around Derived. More importantly, I wish to expose the base class of Derived, Base, by way of a reference. The reason for this is that, ultimately, I wish for Handle to look something like this:
class Handle : public IHandle_<Handle>{
private:
std::unique_ptr<Derived1> myD1;
std::unique_ptr<Derived2> myD2;
public:
Handle(std::unique_ptr<Derived1> aD1)
: myD1(std::move(aD1)),
base1(*aD1),
base2(*aD1){};
Handle(std::unique_ptr<Derived2> aD2)
: myD2(std::move(aD2)),
base1(*aD2),
base2(*aD2){};
Base1& base1;
Base2& base2;
};
The reason I wish for Handle to work like this is that I am using it as a 'Component' in an 'entity component system', and I'd like for this particular component to be instantiatable from two different concrete implementations of the same two base classes. I mention this because an 'entity component system' design pattern by definition departs from traditional object-oriented programming practices: in other words, I know there are other ways of accomplishing what I am trying to do, however I wish to make it work in some variation of what I have listed here.
Question
Why does the simple Handle example shown in my first snippet fail? It compiles fine but seg-faults when trying to access a method in Base. If I change the order in which I instantiate the member variables of Handle, I get some errors at compile time which I think could provide some hints but I do not really understand what is going on.
Here is a full working example of Handle and the classes it depends on:
#include <memory>
#include <iostream>
class Base{
public:
Base(int ax) : x(ax){};
virtual ~Base() = 0;
virtual void setVal(float a) = 0;
virtual float getVal() = 0 ;
int x;
};
Base::~Base(){}
class Derived : public Base{
public:
Derived(int ax, int az)
: Base(ax), z(az){};
int z;
};
class Concrete : public Derived{
public:
Concrete(int ax, int aw, int av)
: Derived(ax, aw),
v(av){};
void setVal(float a) override{
myVal = a;
}
float getVal() override{
return myVal;
}
float myVal;
int v;
};
class IHandle{
public:
virtual ~IHandle() = 0;
};
IHandle::~IHandle(){}
template <class T>
class IHandle_ : public IHandle{
public:
virtual ~IHandle_() = 0;
};
template <class T>
IHandle_<T>::~IHandle_(){};
class Handle : public IHandle_<Handle>{
public:
Handle(std::unique_ptr<Derived> aDerived)
: derived(std::move(aDerived)),
base(*aDerived) {};
std::unique_ptr<Derived> derived;
Base& base;
};
int main(){
// These two pointers are owned by an EntityManager
std::unique_ptr<Derived> ptr(new Concrete(1, 2, 3));
// we can get a reference to an IHandle from the EntityManager
std::unique_ptr<IHandle> aHandle(new Handle(std::move(ptr)));
// We need, specifically, a `Handle` implementation of `IHandle`
Handle& handle = static_cast<Handle&>(*aHandle);
// seg fault on the following line
handle.base.setVal(10.0);
std::cout << "a = " << handle.base.getVal() << std::endl;
return 0;
}
The members in a C++ class are initialized in the order you declare them, so looking at the first snippet, the order of initialization of the members in the Handle class is:
derived
base
That said, it means that in the constructor the line
derived(std::move(aDerived))
will transfer the internal resources of aDerived to derived, reasonably resetting the state of aDerived. So as soon as your code reach the statement
base(*aDerived)
base will reference an empty (depends on your move constructor implementation inside Base and Derived class) object that most likely will be deleted from memory after the call of the constructor itself.
So, I believe that any reference to base you got in your code are pointing to a not allocated memory, giving the SEG_FAULT error.
SEG_FAULT most of the time refers to code that is using (in your case writing, see setval() ) an area of memory not (yet or anymore) allocated for the running process.
Hope this may help,
Have a good night,
Stefano

Contravariant types and extensibility

I'm writing a C++ library for optimization, and I've encountered a curious issue with contra-variant types.
So, I define a hierarchy of "functions", based on what information they can compute.
class Function {
public:
double value()=0;
}
class DifferentiableFunction : public Function {
public:
const double* gradient()=0;
}
class TwiceDifferentiableFunction : public DifferentiableFunction {
public:
const double* hessian()=0;
}
Which is all well and good, but now I want to define interfaces for the optimizers. For example, some optimizers require gradient information, or hessian information in order to optimize, and some don't. So the types of the optimizers are contravariant to the types of the functions.
class HessianOptimizer {
public:
set_function(TwiceDifferentiableFunction* f)=0;
}
class GradientOptimizer : public HessianOptimizer {
public:
set_function(DifferentiableFunction* f)=0;
}
class Optimizer: public GradientOptimizer {
public:
set_function(TwiceDifferentiableFunction* f)=0;
}
Which I suppose makes sense from a type theoretic perspective, but the thing that is weird about it is that usually when people want to extend code, they will inherit the already existing classes. So for example, if someone else was using this library, and they wanted to create a new type of optimizer that requires more information than the hessian, they might create a class like
class ThriceDifferentiableFunction: public TwiceDifferentiableFunction }
public:
const double* thirdderivative()=0;
}
But then to create the corresponding optimizer class, we would have to make HessianOptimizer extend ThirdOrderOptimizer. But the library user would have to modify the library to do so! So while we can add on the ThriceDifferentiableFunction without having to modify the library, it seems like the contravariant types lose this property. This seems to just be an artifact of the fact the classes declare their parent types rather than their children types.
But how are you supposed to deal with this? Is there any way to do it nicely?
Since they're just interfaces, you don't have to be afraid of multiple inheritance with them. Why not make the optimiser types siblings instead of descendants?
class OptimizerBase
{
// Common stuff goes here
};
class HessianOptimizer : virtual public OptimizerBase {
public:
virtual set_function(TwiceDifferentiableFunction* f)=0;
}
class GradientOptimizer : virtual public OptimizerBase {
public:
virtual set_function(DifferentiableFunction* f)=0;
}
class Optimizer : virtual public OptimizerBase {
public:
virtual set_function(TwiceDifferentiableFunction* f)=0;
}
// impl
class MyGradientOptimizer : virtual public GradientOptimizer, virtual public HessianOptimizer
{
// ...
};

Derived Class Calling Non-Public Base Class Virtual Function

EDITED:
This question has already been asked here
but didn't help in my case. I'm trying to have a hierarchy of classes, with inherited public update() functions. But I want a given derived derived class to call the functionality of all of its base classes before doing its own processing. My actual VS2013 solution consists of an EXE project that references a DLL project, but the simplified code below still produces the error:
// Map.h (in DLL project)
namespace Game2D {
class Map {
public:
explicit Map();
~Map();
void update(double);
protected:
virtual void baseUpdates(double dt) {}
};
}
// Map.cpp (in DLL project)
namespace Game2D {
Map::Map() { }
Map::~Map() {}
void Map::update(double dt) {
baseUpdates(dt);
// Do some base stuf...
}
}
// AutoScrollMap.h (in DLL project)
namespace Game2D {
class AutoScrollMap : public Map {
public:
explicit AutoScrollMap();
~AutoScrollMap();
protected:
virtual void baseUpdates(double) {}
};
}
// AutoScrollMap.cpp (in DLL project)
namespace Game2D {
AutoScrollMap::AutoScrollMap() : Game2D::Map() {}
AutoScrollMap::~AutoScrollMap() {}
void AutoScrollMap::baseUpdates(double dt) {
// Do some stuff...
}
}
// DesertMap.h (in EXE project)
namespace Shooter {
class DesertMap : public Game2D::AutoScrollMap {
public:
explicit DesertMap();
~DesertMap();
protected:
virtual void baseUpdates(double);
};
}
// DesertMap.cpp (in EXE project)
namespace Shooter {
DesertMap::DesertMap() : Game2D::AutoScrollMap() {}
DesertMap::~DesertMap() {}
void DesertMap::baseUpdates(double dt) {
AutoScrollMap::baseUpdates(dt);
// Do more specific stuff...
}
}
This gives me a compiler error of "error C2084: function 'void Game2D::AutoScrollMap::baseUpdates(double)' already has a body". The article above says I can use this syntax to call a function that is being overloaded. However, the base function in its example was public, not protected, and I really want to keep baseUpdates() protected since its not part of the interface.
I thought this problem was a fairly basic use of the OOP inheritance paradigm, so what am I missing? All advice is greatly appreciated!
The method you described has no problem, the problem is in your code. You already implemented Derived2::baseUpdates() inline, then you try to define it again. You should change Derived2 to this:
class Derived2 : public Derived1 {
public:
Derived2() : Derived1() { }
protected:
virtual void baseUpdates();
};
void Derived2::baseUpdates() {
Derived1::baseUpdates();
}
Also your Base constructor is not implemented.
Wow, trying to reduce this code to its simplest form for help actually revealed the problem. I had already put braces "{}" after baseUpdates() in AutoScrollMap.h, hence the "function already has body" error. Looks like you sure can call base virtual functions from derived overrides, even if the base function is not public! Sorry for wasting everybody's time, haha.

How do I make my Factory's Header not dependent on the templated objects it creates?

I have an abstract base class like so:
class AbstractBaseClass
{};
a templated concrete class that derives from it:
template<class T>
class ConcreteClass : public AbstractBaseClass
{
public:
ConcreteClass(T input) : data(input) {}
private:
T data;
};
AndI have a factory class that creates AbstractBaseClasses
class MyFactory
{
public:
boost::shared_ptr<AbstractBaseClass> CreateBlah();
boost::shared_ptr<AbstractBaseClass> CreateFoo();
template<class T>
boost::shared_ptr<AbstractBaseClass> Create(T input)
{
return boost::shared_ptr<AbstractBaseClass>(new ConcreteClass<T>(input));
}
};
The problem with this, is that now EVERYTHING that uses MyFactory has to include the entire implementation to ConcreteClass. Ideally, I want nothing but MyFactory to know about ConcreteClass.
Is there any way to architect this to achieve this goal? (Besides manually making a new Create function in MyFactory for every type I want instead of templating it).
you'll need to put the factory implementation into the implementation file (which you mentioned you'd like to avoid, but it is the lesser evil unless the interfaces are small, and/or your projects are small).
of course, there are a few other ways you could approach this, such as putting the implementation into base classes, and making derived bases factories, or using some other really weird template syntax to reduce instantiations in dependent translations. this really comes down to convenience and scale for your project. if you are working on one or more large projects, then full abstraction wrt instantiation will serve your needs best in the long run (assuming you need dynamic polymorphism and memory).
you may also try other approaches (such as overloading) to reduce errors by using type-safety.
the short answer is that you'll really need to abstract the interfaces/instantiation into one or multiple implementation files to remove header dependencies - very common idiom, and many ways to tackle it. you can over course further divide and use polymorphism for your factories as well.
you may also use template forward declarations to minimize the sets to the compilation unit. provided:
/** in MyIntermediateFactory.hpp */
class MyIntermediateFactory {
public:
static template<class T> boost::shared_ptr<T> Create(float);
};
/** in Concrete.hpp */
template<Concrete>
boost::shared_ptr<T> MyIntermediateFactory::Create<Concrete>(float arg) {
/* … */
}
using this you can select portions of programs/interfaces which you need in the library, then wrap it all up in a real Factory (for the build at hand). the linker/instantiation should fail along the way if you actually attempt to request a creation which is not visible.
there a lot of options, really - you need to figure out how big your scale is in order to determine what to abstract (or not). instantiation requires interface, to remove header dependencies, you'll have to abstract the instantiation someplace.
My approach to the same problem in the past was the creation of a set of concrete factories (one per type) that get registered in the global factory (for illustration purposes, indexing by object name):
class AbstractBaseClass;
class ConcreteFactory
{
public:
AbstractBaseClass * create();
};
class AbstractFactory
{
public:
void registerFactory( std::string const & name, std::shared_ptr<ConcreteFactory> const & f )
{
factory[ name ] = f; // check for collisions, complain if so ...
}
AbstractBaseClass * create( std::string const & name )
{
return factory[name]->create(); // check for existence before dereferencing...
}
private:
std::map<std::string, std::shared_ptr<ConcreteFactory> > factory;
};
I used this in a piece of code that was heavily templated to reduce compilation time. Each concrete factory and the class that it creates need only be in a single translation unit that registers the concrete factory. The rest of the code only need to use the common interface to AbstractBaseClass.
I realize I am answering this five years later. Maybe the language has grown a tad since then. I'd like to offer something that seems right, if I understand the question properly, if for no other point than to help others who might find this question and wonder what they could do.
factory.hpp
#include "base.hpp"
namespace tvr
{
namespace test
{
class factory
{
public:
typedef base::ptr Ptr;
enum eSpecial
{
eDerived
};
template<typename Type>
Ptr create()
{
Ptr result;
result.reset(new Type());
return result;
}
template<typename Type, typename DataType>
Ptr create(const DataType& data)
{
Ptr result;
result.reset(new Type(data));
return result;
}
template<typename Type, typename DataType>
Ptr create(const DataType& data, eSpecial tag)
{
Ptr result;
result.reset(new Type());
static_cast<Type*>(result.get())->set_item(data);
return result;
}
};
}
}
base.hpp
#include <memory>
namespace tvr
{
namespace test
{
class base
{
public:
typedef std::shared_ptr<base> ptr;
public:
base() {}
virtual ~base() {}
virtual void do_something() = 0;
};
}
}
some_class.hpp
#include <ostream>
namespace tvr
{
namespace test
{
struct some_class
{
};
}
}
std::ostream& operator<<(std::ostream& out, const tvr::test::some_class& item)
{
out << "This is just some class.";
return out;
}
template_derived.hpp
#include <iostream>
#include "base.hpp"
namespace tvr
{
namespace test
{
template<typename Type>
class template_derived : public base
{
public:
template_derived(){}
virtual ~template_derived(){}
virtual void do_something()
{
std::cout << "Doing something, like printing _item as \"" << _item << "\"." << std::endl;
}
void set_item(const Type data)
{
_item = data;
}
private:
Type _item;
};
}
}
and, finally, main.cpp
#include <vector>
#include "base.hpp"
#include "factory.hpp"
namespace tvr
{
namespace test
{
typedef std::vector<tvr::test::base::ptr> ptr_collection;
struct iterate_collection
{
void operator()(const ptr_collection& col)
{
for (ptr_collection::const_iterator iter = col.begin();
iter != col.end();
++iter)
{
iter->get()->do_something();
}
}
};
}
}
#include "template_derived.hpp"
#include "some_class.hpp"
namespace tvr
{
namespace test
{
inline int test()
{
ptr_collection items;
tvr::test::factory Factory;
typedef template_derived<unsigned int> UIntConcrete;
typedef template_derived<double> DoubleConcrete;
typedef template_derived<std::string> StringConcrete;
typedef template_derived<some_class> SomeClassConcrete;
items.push_back(Factory.create<SomeClassConcrete>(some_class(), tvr::test::factory::eDerived));
for (unsigned int i = 5; i < 7; ++i)
{
items.push_back(Factory.create<UIntConcrete>(i, tvr::test::factory::eDerived));
}
items.push_back(Factory.create<DoubleConcrete>(4.5, tvr::test::factory::eDerived));
items.push_back(Factory.create<StringConcrete>(std::string("Hi there!"), tvr::test::factory::eDerived));
iterate_collection DoThem;
DoThem(items);
return 0;
}
}
}
int main(int argc, const char* argv[])
{
tvr::test::test();
}
output
Doing something, like printing _item as "This is just some class.".
Doing something, like printing _item as "5".
Doing something, like printing _item as "6".
Doing something, like printing _item as "4.5".
Doing something, like printing _item as "Hi there!".
This uses a combination of templates, function overloading, and tagging through enums to help create a flexible factory class that doesn't require knowing much about the individual classes it instantiates, to include templated concrete classes as the OP asked about.
The 'eDerived' tag (in the form of an enum) tells the compiler to use the version of the factory's create function that takes a class like the template_derived class, which has a function that allows me to assign data to one of its members. As you can tell from the way I ordered the headers in main.cpp, the factory doesn't know anything about template_derived. Neither does the function calling the base class's virtual function (do_something). I think this is what the OP wanted, but without having to add a various create functions within every class that this factory might generate.
I also showed how one doesn't have to explicitly create functions for each class the factory should create. The factory's overloaded create functions can create anything derived from the base class that matches the appropriate signature.
I didn't do an extensive performance analysis on this code, but I did enough to see that the majority of the work happens in the streaming operator. This compiles in about 1 second on my 3.30Ghz quad core machine. You might need to experiment with more robust code to see how badly it might bog down the compiler, if much at all.
I've tested this code in VC++ 2015, although it probably works in other compilers pretty easily. If you want to copy this, you'll need to add your own guard headers. In any event, I hope this is useful.
You could use explicit template instanciation. Trying to call the factory method with a template parameter not explicit instanciated will give you a linker error. Note the explicit template instanciation in MyFactory.cpp
template AbstractBaseClass* MyFactory::Create(int input);
All put together looks like this (I removed shared_ptr for the sake of simplicity):
Main.cpp:
#include "AbstractBaseClass.h"
#include "MyFactory.h"
//we do not need to know nothing about concreteclass (neither MyFactory.h includes it)
int main()
{
MyFactory f;
AbstractBaseClass* ab = f.Create(10);
ab = f.Create(10.0f);
return 0;
}
MyFactory.h:
#include "AbstractBaseClass.h"
class MyFactory
{
public:
template<class T>
AbstractBaseClass* Create(T input);
};
MyFactory.cpp:
#include "MyFactory.h"
#include "ConcreteClass.h"
template<class T>
AbstractBaseClass* MyFactory::Create(T input) {
return new ConcreteClass<T>(input);
}
//explicit template instanciation
template AbstractBaseClass* MyFactory::Create(int input);
//you could use as well specialisation for certain types
template<>
AbstractBaseClass* MyFactory::Create(float input) {
return new ConcreteClass<float>(input);
}
AbstractBaseClass.h:
class AbstractBaseClass{};
ConcreteClass.h:
#include "AbstractBaseClass.h"
template<class T>
class ConcreteClass : public AbstractBaseClass
{
public:
ConcreteClass(T input) : data(input) {}
private:
T data;
};
You're looking for the "PIMPL" idiom. There's a good explanation at Herb Sutter's GOTW site
It can't be done because ConcreteClass is a template, that means you need the complete implementation available at compile time. Same reason why you can't precompile templates and have to write them all in header files instead.

Registering derived classes in central list

I have a central list of implementations of an interface and would like for derived classes to be able to register themselves in that list without having to add them in some central place. For example:
// interface.h
struct MyInterface;
std::vector<MyInterface*>& InterfaceList();
struct MyInterface {
MyInterface() {
InterfaceList().push_back(this);
}
virtual ~MyInterface() {}
// ...
};
// derived.cpp
#include "interface.h"
class MyImplementation: public MyInterface {
public:
MyImplementation() {
}
// ...
};
MyImplementation impl;
This doesn't seem to work. For reasons I don't understand, the constructor of MyInterface never gets called - I would have thought that the instance of the derived class would call it at startup. I know it's possible to do something along these lines since I've seen other libraries doing it - but haven't managed to figure out what it is that I'm doing wrong.
Thanks :)
Edit: Sorry, missed a pair of braces and a reference. InterfaceList() is a function that returns a reference to a vector.
Edit part 2: Have now got it working in a reduced example, but can't get it to work in the files for the derived implementations - but that technique is working in another project. There must be something slightly different in those files which is causing it to fail - but it appears the problem isn't in the code I posted. Don't really want to post big chunks of my employer's projects though so I guess I'll have to keep fiddling myself. Thanks for the suggestions so far though :)
You example does not compile under VS2008. What compiler are you using? When you change the second line in interface.h to
std::vector<MyInterface*> InterfaceList;
it works correctly. Just drop the braces.
I had a similar problem recently, and found that the simplest solution was to create a templated base class that was responsible for registering all of my implementations.
The base class contains a static variable, of templated type T, and this is registered with the central list. At runtime, each implementation would create its own static object and in the process of creating itself would register with the central list.
#include <iostream>
#include <vector>
class ITestInterface
{
public:
virtual void Execute() = 0;
};
std::vector<ITestInterface *> InterfaceList;
template <class T> class BaseClass :
public ITestInterface
{
public:
virtual void Execute() = 0;
protected:
BaseClass()
{
InterfaceList.push_back(&s_thing);
}
private:
static T s_thing;
};
template <class T> T BaseClass<T>::s_thing;
class ImplementationOne :
public BaseClass<ImplementationOne>
{
public :
ImplementationOne():
BaseClass()
{
;
}
void Execute()
{
std::cout << "ImplementationOne Execute\r\n";
}
};
class ImplementationTwo :
public BaseClass<ImplementationTwo>
{
public :
ImplementationTwo():
BaseClass()
{
;
}
void Execute()
{
std::cout << "ImplementationTwo Execute\r\n";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<ITestInterface *>::iterator it = InterfaceList.begin();
for(; it != InterfaceList.end(); it++)
{
(*it)->Execute();
}
}
The thing to remember with this code is that the line
static T s_thing;
does not result in a single s_thing, rather because a template is a type-generator there is one static s_thing for each derived class.
The output is
ImplementationOne Execute
ImplementationTwo Execute
This code works in VS2010.
This is the issue:
std::vector<MyInterface*> InterfaceList();
should be
std::vector<MyInterface*> InterfaceList;
Following definition of InterfaceList is a kind of function declaration which returns std::vector
std::vector<MyInterface*> InterfaceList();
Change this to
std::vector<MyInterface*> InterfaceList;