I have a library where there is a lot of small objects, which now all have virtual functions. It goes to such an extent that the size of the pointer to a virtual function table can exceed the size of the useful data in the object (it can often be just a structure with a single float in it). The objects are elements in a numerical simulation on a sparse graph, and as such cannot be easily merged / etc.
I'm not concerned as much about the cost of the virtual function call, rather about the cost of the storage. What is happening is that the pointer to the virtual function table is basically reducing the efficiency of the cache. I'm wondering if I would be better off with a type id stored as an integer, instead of the virtual function.
I cannot use static polymorphism, as all of my objects are in a single list, and I need to be able to perform operations on items, selected by an index (which is a runtime value - therefore there is no way to statically determine the type).
The question is: is there a design pattern or a common algorithm, that can dynamically call a function from an interface, given a list of types (e.g. in a typelist) and a type index?
The interface is defined and does not change much, but new objects will be declared in the future by (possibly less-skilled) users of the library and there should not be a large effort needed in doing so. Performance is paramount. Sadly, no C++11.
So far, I have perhaps a silly proof of concept:
typedef MakeTypelist(ClassA, ClassB, ClassC) TList; // list of types
enum {
num_types = 3 // number of items in TList
};
std::vector<CommonBase*> uniform_list; // pointers to the objects
std::vector<int> type_id_list; // contains type ids in range [0, num_types)
template <class Op, class L>
class Resolver { // helper class to make a list of functions
typedef typename L::Head T;
// specialized call to op.Op::operator ()<T>(p)
static void Specialize(CommonBase *p, Op op)
{
op(*(T*)p);
}
// add a new item to the list of the functions
static void BuildList(void (**function_list)(CommonBase*, Op))
{
*function_list = &Specialize;
Resolver<Op, typename L::Tail>::BuildList(function_list + 1);
}
};
template <class Op>
class Resolver<Op, TypelistEnd> { // specialization for the end of the list
static void BuildList(void (**function_list)(CommonBase*, Op))
{}
};
/**
* #param[in] i is index of item
* #param[in] op is a STL-style function object with template operator ()
*/
template <class Op>
void Resolve(size_t i, Op op)
{
void (*function_list[num_types])(CommonBase*, Op);
Resolver<Op, TList>::BuildList(function_list);
// fill the list of functions using the typelist
(*function_list[type_id_list[i]])(uniform_list[i], op);
// call the function
}
I have not looked into the assembly yet, but I believe that if made static, the function pointer array creation could be made virtually for free. Another alternative is to use a binary search tree generated on the typelist, which would enable inlining.
I ended up using the "thunk table" concept that I outlined in the question. For each operation, there is a single instance of a thunk table (which is static and is shared through a template - the compiler will therefore automatically make sure that there is only a single table instance per operation type, not per invokation). Thus my objects have no virtual functions whatsoever.
Most importantly - the speed gain from using simple function pointer instead of virtual functions is negligible (but it is not slower, either). What gains a lot of speed is implementing a decision tree and linking all the functions statically - that improved the runtime of some not very compute intensive code by about 40%.
An interesting side effect is being able to have "virtual" template functions, which is not usually possible.
One problem that I needed to solve was that all my objects needed to have some interface, as they would end up being accessed by some calls other than the functors. I devised a detached facade for that. A facade is a virtual class, declaring the interface of the objects. A detached facade is instance of this virtual class, specialized for a given class (for all in the list, operator [] returns detached facade for the type of the selected item).
class CDetachedFacade_Base {
public:
virtual void DoStuff(BaseType *pthis) = 0;
};
template <class ObjectType>
class CDetachedFacade : public CDetachedFacade_Base {
public:
virtual void DoStuff(BaseType *pthis)
{
static_cast<ObjectType>(pthis)->DoStuff();
// statically linked, CObjectType is a final type
}
};
class CMakeFacade {
BaseType *pthis;
CDetachedFacade_Base *pfacade;
public:
CMakeFacade(BaseType *p, CDetachedFacade_Base *f)
:pthis(p), pfacade(f)
{}
inline void DoStuff()
{
f->DoStuff(pthis);
}
};
To use this, one needs to do:
static CDetachedFacade<CMyObject> facade;
// this is generated and stored in a templated table
// this needs to be separate to avoid having to call operator new all the time
CMyObject myobj;
myobj.DoStuff(); // statically linked
BaseType *obj = &myobj;
//obj->DoStuff(); // can't do, BaseType does not have virtual functions
CMakeFacade obj_facade(obj, &facade); // choose facade based on type id
obj_facade.DoStuff(); // calls CMyObject::DoStuff()
This allows me to use the optimized thunk table in the high performance portion of the code and still have polymorphically behaving objects to be able to conveniently handle them where performance is not required.
CRTP is a compile time alternative to virtual functions:
template <class Derived>
struct Base
{
void interface()
{
// ...
static_cast<Derived*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
Derived::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
It relies on the fact that definition of the member are not instantiated till they are called. So Base should refer to any member of Derived only in the definition of its member functions, never in prototypes or data members
Related
In general, my question was simple, I want to imlement some design pattern, which allows following:
there is exists some predefined interface (Interface class);
and exists class (Utilizer), which accepts another class (via pointer, reference, smart-pointer, whatever else...) implementing predefined interface, and stars using this class via the interface;
class Utilizer should be able to own other class passed to it (which implements Interface) and delete it when Utilizer is destroyed.
In managed languages (like C#, Java) this can be implemented in simple way: class Utilizer might accept reference to base class (Interface) and hold this reference in the class, and use interface via the reference. On destruction of Utilizer class, the garbage collector might delete class, which implements `Interface'.
In C++ we have no garbage collector... Ok, we can use some smart_pointer, but this might be not generic smart pointer, but smart pointer of some particular type (for example, unique_ptr with user specified deleter, because class, which implements Interface is resided in shared memory and regular operator delete() can't be applied to this class...)
And second nuisance: virtual functions. Of course, when you are using managed languages you may not notice this. But if you made Interface class as abstract base class (with virtual keyword), then you will notice, that in test function (see the code below) compiler performs indirect calls (via function pointers). This happens because compiler needs to access virtual functions table. The call via function pointer is not very heavy (few processor ticks, or event tens of ticks), but the major issue is that compiler doesn't see that happens next, after the indirection. Optimizer stops here. Functions can't be inlined anymore. And we get not optimal code, which doesn't reduces to few machine instructions (for example test function reduces in the example to loading of two constant and calling printf function), we get unoptimal "generic" implementation, which effectively nullifies all the benefits of C++.
There is typical solution to avoid getting of unoptimal code -- avoid using virtual functions (prefer CRTP pattern instead), avoid type erasure (in the example, Utilizer class might store not Accessor, but std::function<Interface<T>&()> -- this solution is nice, but indirection in std::function leads to generation of unoptimal code again).
And the essence of the question, how to implement the logic described above (class which owns other abstract, non some particular, class and uses it) in C++ effectively?
Not sure if I was able to clearly express my thought. Below is the my implementation with the comments. It generates optimal code (see disassembly of test function in live demo live demo), all is inlined as expected. But the whole implementation looks cumbersome.
I would like to hear how can I improve the code.
#include <utility>
#include <memory>
#include <functional>
#include <stdio.h>
#include <math.h>
// This type implements interface: later Utilizer class
// accept Accessor type, which was able to return reference
// to object of some type, which implements this interface,
// and Utilizer class uses returned object via this interface.
template <typename Impl> class Interface
{
public:
int oper(int arg) { return static_cast<Impl*>(this)->oper(arg); }
const char *name() const { return static_cast<const Impl*>(this)->name(); }
};
// Class which uses object, returned by Accessor class, via
// predefined interface of type Interface<Impl>.
// Utilizer class can perform operations on any class
// which inherited from Interface class, but Utilizer
// doesn't directly owns parficular instance of the
// class implementing Interface: Accessor serves for
// getting of particular implementation of Interface
// from somewhere.
template <typename Accessor> class Utilizer
{
private:
typedef typename std::remove_reference<decltype(std::declval<Accessor>()())>::type Impl;
Accessor accessor;
// This static_cast allows only such Accessor types, for
// which operator() returns class inherited from Interface
Interface<Impl>& get() const { return static_cast<Interface<Impl>&>(accessor()); }
public:
template <typename...Args> Utilizer(Args&& ...args) : accessor(std::forward<Args>(args)...) {}
// Following functions is the public interface of Utilizer class
// (this interface have no relations with Interface class,
// except of the fact, that implementation uses Interface class):
double func(int a, int b)
{
if (a > 0) return sqrt(get().oper(a) + b);
else return get().oper(b) * a;
}
const char *text() const
{
const char *result = get().name();
if (result == nullptr) return "unknown";
return result;
}
};
// This is implementation of Interface<Impl> interface
// (program may have multiple similar classes and Utilizer
// can work with any of these classes).
struct Implementation : public Interface<Implementation>
{
Implementation() { puts("Implementation()"); }
Implementation(const Implementation&) { puts("copy Implementation"); }
~Implementation() { puts("~Implementation()"); }
// Following functions are implementation of functions
// defined in Interface<Impl>:
int oper(int arg) { return arg + 42; }
const char *name() const { return "implementation"; }
};
// This is class which owns some particular implementation
// of the class inherited from Interface. This class only
// owns the class which was given to it and allows accessing
// this class via operator(). This class is intendent to be
// template argument for Utilizer class.
template <typename SmartPointer> struct Owner
{
SmartPointer p;
Owner(Owner&& other) : p(std::move(other.p)) {}
template <typename... Args> Owner(Args&&...args) : p(std::forward<Args>(args)...) {}
Implementation& operator()() const { return *p; }
};
typedef std::unique_ptr<Implementation> PtrType;
typedef Utilizer<Owner<PtrType> > UtilType;
void test(UtilType& utilizer)
{
printf("%f %s\n", utilizer.func(1, 2), utilizer.text());
}
int main()
{
PtrType t(new Implementation);
UtilType utilizer(std::move(t));
test(utilizer);
return 0;
}
Your CPU is smarter than you think. Modern CPUs are absolutely capable of guessing the target of, and speculatively executing through, an indirect branch. The speed of the L1 cache, and register renaming, often remove most or all of the extra cost of a non-inlined call. And the 80/20 rule applies in spades: Your test code's bottleneck is the internal processing done by puts, not the late binding you're trying to avoid.
To answer your question, you could improve your code by removing all that template stuff: it would be just as fast, and more maintainable (hence more practical to do actual optimization). Optimization of algorithms and data structures should often be done up-front; optimization of low-level instruction streams should never, ever, ever be done except after analyzing profiling results.
Is it possible to perform double dispatch with runtime polymorphism?
Say I have some classes, and some of those classes can be added/multiplied/etc., and I want to store those dynamically within another class that performs type erasure at runtime. Then say I want to perform basic operations on the data held within that class.
The way to handle this (as far as I'm aware) is to use double dispatch to specialize the operation. However, all of the solutions I have encountered rely on the fact that you have a numerable amount of types, and then use virtual function calls or dynamic_casts, if-else, and RTTI to deduce the type at runtime. Because the data held within the class isn't known until runtime, I can't create a bunch of virtual methods or do a brute force check on the types. So I figured the visitor pattern would be the best solution, but even then, I can't seem to get whether or not this is possible.
I have a wrapper class that holds a smart pointer to a nested polymorphic class to implement the type erasure and runtime polymorphism, but I can't figure out if it's possible to use the visitor pattern to do double dispatch on this.
Note that the code below is incomplete, it just shows my thought process.
class Wrapper {
private:
class Concept;
template<typename T> class Model;
class BaseVisitor {
public:
virtual ~Visitor() = default;
virtual void visit(Concept &) = 0;
};
template<typename T>
class Visitor : public BaseVisitor {
private:
T first_;
public:
Visitor(T first) : first_(first) {}
virtual void visit(Concept &other) override {
// perform addition
}
};
class Concept {
public:
virtual ~Concept() = default;
virtual void add(Concept &m) const = 0;
virtual void accept(BaseVisitor &visitor) const = 0;
};
template<typename T>
class Model final : public Concept {
private:
T data_;
public:
Model(T m)
: data_(m) {}
virtual void add(Concept &m) const override {
Visitor<T> v(data_);
m.accept(v);
};
virtual void accept(BaseVisitor &visitor) const override {
visitor.visit(*this);
};
};
std::shared_ptr<const Concept> ptr_;
// This isn't right, it just illustrates what I'm trying to do.
// friend Something operator+(Wrapper &lhs, Wrapper &rhs) {
// return (*lhs.ptr_).add(*rhs.ptr_);
// }
public:
template<typename T>
Wrapper(T value) : ptr_(std::make_shared<Model<T>>(value)) {}
};
I've looked into implementing double dispatch using function pointers, template specialization, and static type IDs as well, but I can't seem to figure out how to make it work.
Is this even possible?
EDIT
Based on the comments below, in order to be more specific and to give a little more background, I am using templated classes that use template functions to perform basic operations like addition and multiplication. However, I would also like to store those templated classes within a vector, hence the type erasure. Now, if I wanted to do operations on those classes after I perform the type erasure, I need some way to deduce the type for the templated function. However, since I can't easily get the internal held type back from the Wrapper, I am hoping that there is a way I can call the correct template function on the data held within the Wrapper::Model<T> class, whether that is a visitor pattern, static type IDs, whatever.
To be even more specific, I am working with classes to do delayed evaluation and symbolic computations, meaning I have classes such as Number<T>, which can be Number<int>, Number<double>, etc. and classes such as Variable, Complex<T> and all of the TMP combinations for various operations, such as Add<Mul<Variable, Variable>, Number<double>>, etc.
I can work with all of these fine at compile-time, but then I need to be able to store these in a vector -- something like std::vector<Wrapper> x = {Number<int>, Variable, Add<Number<double>, Variable>};. My best guess at this was to perform type erasure to store the expressions inside the polymorphic Wrapper. This serves double-duty to enable runtime parsing support of symbolic expressions.
However, the functions I wrote to handle the addition, such as
template<typename T1, typename T2>
const Add<T1, T2> operator+(const T1 &lhs, const T2 &rhs)
{ return Add<T1, T2>(lhs, rhs); }
can't accept Wrapper and pull the type out (due to the type erasure). I can, however, insert the Wrapper into the Add expression class, meaning I can carry around the hidden types. The problem is when I actually get down to evaluating the result of something like Add<Wrapper, Wrapper>. In order to know what this comes out to, I'd need to figure out what's actually inside or to do something along the lines of double dispatch.
The main problem is that the examples for double dispatch that most closely match my problem, like this question on SO, rely on the fact that I can write out all of the classes, such as Shapes, Rectangles. Since I can't explicitly do that, I'm wondering if there's a way to perform double dispatch to evaluate the expression based on the data held inside the Model<T> class above.
I will put my question first and add some longer explanation below. I have the following class design which is not working as C++ does not support virtual template methods. I would be happy to learn about alternatives and workarounds to implement this behaviour.
class LocalParametersBase
{
public:
template<unsigned int target>
virtual double get() const = 0; //<--- not allowed by C++
};
template<unsigned int... params>
class LocalParameters : public LocalParametersBase
{
public:
template<unsigned int target>
double get() const; //<--- this function should be called
};
Using a simple function argument instead of the template parameter is at the moment no alternative for the following reasons:
The implementation of this method in the derived class relies on some template meta-programming (using the variadic class template arguments). As far as I know it is not possible to use function arguments (even if they are of constant integral type) as template arguments.
The method will be only called with compile-time constants. Performance is crucial in my application and therefore I want to benefit from the calculation at compile time.
The common base class is needed (I have left out the rest of the interface for brevity).
Any suggestions are highly appreciated.
Update: Motivation
As there were many questions about the motivation for this kind of layout, I'll try to explain it with a simple example. Imagine you want to measure a trajectory in a three-dimensional space, In my specific example these are tracks of charged particles (of fixed mass) in a magnetic field. You measure these tracks by sensitive detectors which are approximated as 2D surfaces. At each intersection of a track with a sensitive detector, the trajectory is uniquely identified by 5 parameters:
two local coordinates describing the intersection point of the track with the surface in the local coordinate system of the detector surface (that's why the class names are chosen this way),
two angles specifying the direction of the trajectory,
one parameter containing the information about the momentum and the electric charge of the particle.
A trajectory is therefore completely identified by a set of five parameters (and the associated surface). However, individual measurements only consist of the first two parameters (the intersection point in the local 2D coordinate system of the surface). These coordinate systems can be of different types (kartesian, cylindrical, spherical etc). So each measurement potentially constraints different parameters out of the full set of 5 parameters (or maybe even non-linear combinations of those). Nevertheless, a fitting algorithm (think of a simple chi2 minimizer for instance) should not depend of the specific type of a measurement. It only needs to calculate residuals. That looks like
class LocalParametersBase
{
public:
virtual double getResidual(const AtsVector& fullParameterSet) const = 0;
};
This works fine as each derived class knows how to map the full 5-d parameter set on its local coordinate system and then it can calculate the residuals. I hope this explains a bit why I need a common base class. There are other framework related reasons (such like the existing I/O infrastructure) which you could think of as external constraints.
You may be wondering that the above example does not require to have the templated get method I am asking about. Only the base class is supposed to be exposed to the user. Therefore it would be very confusing if you have a list of LocalParameterBase objects and you can fit a trajectory using them. You even can get the values of the measured local parameters. But you can't access the information which values where actually measured (which renders the previous information useless).
I hope this could shed some light on my problem. I appreciate all the comments received so far.
For my current project I am writing a class whose main purpose is to act as a wrapper around a sparse vector of fixed size. Instead of storing the whole vector (which is the representation of some system state) my class has a vector of reduced size as member variable (= corresponding to a sub-domain of the total parameter space). I hope the illustration below gives you an idea of what I am trying to describe:
VectorType(5) allParameters = {0.5, 2.1, -3.7, 4, 15/9}; //< full parameter space
VectorType(2) subSpace = {2.1, 4}; //< sub domain only storing parameters with index 1 and 3
In order to be able to make the connection to the original vector, I need to "store" the indexes which are copied to my "shortened" vector. This is achieved using non-type variadic template parameters. I also need to be able to query the value of the parameter with a certain index. This should yield a compile time error in case this parameter is not stored in the "shortened" vector. My simplified code for this looks like:
template<unsigned int... index>
class LocalParameters
{
public:
template<unsigned int target>
double get() const;
private:
AtsVectorX m_vValues;
};
LocalParameters<0,1,4> loc;
//< ... do some initialisation ...
loc.get<1>(); //< query value of parameter at index 1
loc.get<2>(); //<-- this should yield a compile time error as the parameter at index 2 is not stored in this local vector class
I managed to implement this behaviour using some simple template programming. But other parts of my code need to treat these "shortened" vectors uniformly through one interface. I still want to be able to access through the interface LocalParametersBase the information whether a parameter with a specific index is stored (if not I want to get a compile time error), and if yes, I would like to access the value of this parameter. In code this should look similar to
LocalParametersBase* pLoc = new LocalParameters<0,1,3>();
pLoc->get<1>();
A suggestion
Without more information about what you are doing, I am only making educated guesses about what is driving you towards this approach.
A common performance problem with code that depends on a virtual interface is that the framework provides generic functionality that dispatches to the virtual methods at very high frequency. This seems to be the issue that you are facing. You have code that is performing computation on sparse vectors, and you want to provide to it a generic interface representing each sparse vector you happen to create.
void compute (LocalParametersBase *lp) {
// code that makes lots of calls to lp->get<4>()
}
However, an alternative approach is to make the computation generic by using a template parameter to represent the derived object type being manipulated.
template <typename SPARSE>
void perform_compute (SPARSE *lp) {
// code that makes lots of calls to lp->get<4>()
}
Each get<> call in the template version of compute is against the derived object. This allows the computation to occur as fast as if you had written code to directly manipulate a LocalParameters<0,1,4>, rather than performing a dynamic dispatch per get<> call.
If you must allow the framework control when the computation is performed, and so the computation is performed on the base class, the base class version can dispatch to a virtual method.
class ComputeBase {
public:
virtual void perform_compute () = 0;
};
void compute (LocalParametersBase *lp) {
auto c = dynamic_cast<ComputeBase *>(lp);
c->perform_compute();
}
By using CRTP, you can create a helper class that takes the derived type as a template parameter, and it implements this virtual method by passing in the derived. Thus, the computation only costs one dynamic dispatch, and the rest of the computation is performed on the actual sparse vector itself.
template <typename Derived>
class CrtpCompute : public ComputeBase {
void perform_compute () {
auto d = static_cast<Derived *>(this);
perform_compute(d);
}
};
Now your sparse vector derives from this helper class.
template <unsigned int... params>
class LocalParameters
: public LocalParametersBase,
public CrtpCompute<LocalParameters<params...>> {
public:
template <unsigned int target> double get() const;
};
Making your interface work the way you have specified it
After the results are computed, you want to place the resulting sparse vector into a container for later retrieval. However, that should no longer be a performance sensitive operation, so you can use the method described below to achieve that.
Base template method → Base template class virtual method → Derived template method
If you are wish to use polymorphism, then delegate the template method call in the base class to a virtual function. Since it is a template method, the virtual function has to come from a template class. You can use a dynamic cast to get to the corresponding template class instance.
template <unsigned int target>
class Target {
public:
virtual double get() const = 0;
};
class LocalParametersBase {
public:
virtual ~LocalParametersBase () = default;
template <unsigned int target> double get() const {
auto d = dynamic_cast<const Target<target> *>(this); // XXX nullptr
return d->get();
}
};
To automate the implementation of the virtual methods for each Target, you can again use CRTP, passing in the derived type to the helper. The helper casts to the derived type to invoke the corresponding template method.
template <typename, unsigned int...> class CrtpTarget;
template <typename Derived, unsigned int target>
class CrtpTarget<Derived, target> : public Target<target> {
double get() const {
auto d = static_cast<const Derived *>(this);
return d->template get<target>();
}
};
template <typename Derived, unsigned int target, unsigned int... params>
class CrtpTarget<Derived, target, params...>
: public CrtpTarget<Derived, target>,
public CrtpTarget<Derived, params...> {
};
And now, you inherit appropriately from your derived class.
template <unsigned int... params>
class LocalParameters
: public LocalParametersBase,
public CrtpCompute<LocalParameters<params...>>,
public CrtpTarget<LocalParameters<params...>, params...> {
public:
template <unsigned int target> double get() const;
};
I am trying to write a class that I can store and use type information in without the need for a template parameter.
I want to write something like this:
class Example
{
public:
template<typename T>
Example(T* ptr)
: ptr(ptr)
{
// typedef T EnclosedType; I want this be a avaialable at the class level.
}
void operator()()
{
if(ptr == NULL)
return;
(*(EnclosedType*)ptr)(); // so i can cast the pointer and call the () operator if the class has one.
}
private:
void* ptr;
}
I am not asking how to write an is_functor() class.
I want to know how to get type information in a constructor and store it at the class level. If that is impossible, a different solution to this would be appreciated.
I consider this as a good and valid question, however, there is no general solution beside using a template parameter at the class level. What you tried to achieve in your question -- using a typedef inside a function and then access this in the whole class -- is not possible.
Type erasure
Only if you impose certain restrictions onto your constructor parameters, there are some alternatives. In this respect, here is an example of type erasure where the operator() of some given object is stored inside a std::function<void()> variable.
struct A
{
template<typename T>
A(T const& t) : f (std::bind(&T::operator(), t)) {}
void operator()() const
{
f();
}
std::function<void()> f;
};
struct B
{
void operator()() const
{
std::cout<<"hello"<<std::endl;
}
};
int main()
{
A(B{}).operator()(); //prints "hello"
}
DEMO
Note, however, the assumptions underlying this approach: one assumes that all passed objects have an operator of a given signature (here void operator()) which is stored inside a std::function<void()> (with respect to storing the member-function, see here).
Inheritance
In a sense, type erasure is thus like "inheriting without a base class" -- one could instead use a common base class for all constructor parameter classes with a virtual bracket operator, and then pass a base class pointer to your constructor.
struct A_parameter_base
{
void operator()() const = 0;
};
struct B : public A_parameter_base
{
void operator()() const { std::cout<<"hello"<<std::endl; }
};
struct A
{
A(std::shared_ptr<A_parameter_base> _p) : p(_p) {}
void operator()()
{
p->operator();
}
std::shared_ptr<A_parameter_base> p;
}
That is similar to the code in your question, only that it does not use a void-pointer but a pointer to a specific base class.
Both approaches, type erasure and inheritance, are similar in their applications, but type erasure might be more convenient as one gets rid of a common base class. However, the inheritance approach has the further advantage that you can restore the original object via multiple dispatch
This also shows the limitations of both approaches. If your operator would not be void but instead would return some unknown varying type, you cannot use the above approach but have to use templates. The inheritance parallel is: you cannot have a virtual function template.
The practical answer is to store either a copy of your class, or a std::ref wrapped pseudo-reference to your class, in a std::function<void()>.
std::function type erases things it stores down to 3 concepts: copy, destroy and invoke with a fixed signature. (also, cast-back-to-original-type and typeid, more obscurely)
What it does is it remembers, at construction, how to do these operations to the passed in type, and stores a copy in a way it can perform those operations on it, then forgets everything else about the type.
You cannot remember everything about a type this way. But almost any operation with a fixed signature, or which can be intermediaried via a fixed signature operation, can be type erased down to.
The first typical way to do this are to create a private pure interface with those operations, then create a template implementation (templated on the type passed to the ctor) that implements each operation for that particular type. The class that does the type erasure then stores a (smart) pointer to the private interface, and forwards its public operations to it.
A second typical way is to store a void*, or a buffer of char, and a set of pointers to functions that implement the operations. The pointers to functions can be either stored locally in the type erasing class, or stored in a helper struct that is created statically for each type erased, and a pointer to the helper struct is stored in the type erasing class. The first way to store the function pointers is like C-style object properties: the second is like a manual vtable.
In any case, the function pointers usually take one (or more) void* and know how to cast them back to the right type. They are created in the ctor that knows the type, either as instances of a template function, or as local stateless lambdas, or the same indirectly.
You could even do a hybrid of the two: static pimpl instance pointers taking a void* or whatever.
Often using std::function is enough, manually writing type erasure is hard to get right compared to using std::function.
Another version to the first two answers we have here - that's closer to your current code:
class A{
public:
virtual void operator()=0;
};
template<class T>
class B: public A{
public:
B(T*t):ptr(t){}
virtual void operator(){(*ptr)();}
T*ptr;
};
class Example
{
public:
template<typename T>
Example(T* ptr)
: a(new B<T>(ptr))
{
// typedef T EnclosedType; I want this be a avaialable at the class level.
}
void operator()()
{
if(!a)
return;
(*a)();
}
private:
std::unique_ptr<A> a;
}
I need to store multiple types of a template class in a single vector.
Eg, for:
template <typename T>
class templateClass{
bool someFunction();
};
I need one vector that will store all of:
templateClass<int> t1;
templateClass<char> t2;
templateClass<std::string> t3;
etc
As far as I know this is not possible, if it is could someone say how?
If it isn't possible could someone explain how to make the following work?
As a work around I tried to use a base, non template class and inherit the template class from it.
class templateInterface{
virtual bool someFunction() = 0;
};
template <typename T>
class templateClass : public templateInterface{
bool someFunction();
};
I then created a vector to store the base "templateInterface" class:
std::vector<templateInterface> v;
templateClass<int> t;
v.push_back(t);
This produced the following error:
error: cannot allocate an object of abstract type 'templateInterface'
note: because the following virtual functions are pure within 'templateInterface'
note: virtual bool templateInterface::someFunction()
To fix this error I made the function in templateInterface not a pure virtual by providing a function body, this compiled but when calling the function the overide is not used, but instead the body in the virtual function.
Eg:
class templateInterface{
virtual bool someFunction() {return true;}
};
template <typename T>
class templateClass : public templateInterface{
bool someFunction() {return false;}
};
std::vector<templateInterface> v;
templateClass<int> i;
v.push_back(i);
v[0].someFunction(); //This returns true, and does not use the code in the 'templateClass' function body
Is there any way to fix this so that the overridden function is used, or is there another workaround to store multiple template types in a single vector?
Why your code doesn't work:
Calling a virtual function on a value doesn't use polymorphism. It calls the function which is defined for the type of this exact symbol as seen by the compiler, not the runtime type. When you insert sub types into a vector of the base type, your values will be converted into the base type ("type slicing"), which is not what you want. Calling functions on them will now call the function as defined for the base type, since not it is of that type.
How to fix this?
The same problem can be reproduced with this code snippet:
templateInterface x = templateClass<int>(); // Type slicing takes place!
x.someFunction(); // -> templateInterface::someFunction() is called!
Polymorphism only works on a pointer or reference type. It will then use the runtime type of the object behind the pointer / reference to decide which implementation to call (by using it's vtable).
Converting pointers is totally "safe" with regard to type slicing. Your actual values won't be converted at all and polymorphism will work as expected.
Example, analogous to the code snippet above:
templateInterface *x = new templateClass<int>(); // No type slicing takes place
x->someFunction(); // -> templateClass<int>::someFunction() is called!
delete x; // Don't forget to destroy your objects.
What about vectors?
So you have to adopt these changes in your code. You can simply store pointers to actual types in the vector, instead of storing the values directly.
When working with pointers you also have to care about deleting your allocated objects. For this you can use smart pointers which care about deletion automatically. unique_ptr is one such smart pointer type. It deletes the pointee whenever it goes out of scope ("unique ownership" - the scope being the owner). Assuming the lifetime of your objects is bound to the scope this is what you should use:
std::vector<std::unique_ptr<templateInterface>> v;
templateClass<int> *i = new templateClass<int>(); // create new object
v.push_back(std::unique_ptr<templateInterface>(i)); // put it in the vector
v.emplace_back(new templateClass<int>()); // "direct" alternative
Then, call a virtual function on one of these elements with the following syntax:
v[0]->someFunction();
Make sure you make all functions virtual which should be possible to be overridden by subclasses. Otherwise their overridden version will not be called. But since you already introduced an "interface", I'm sure you are working with abstract functions.
Alternative approaches:
Alternative ways to do what you want is to use a variant type in the vector. There are some implementations of variant types, the Boost.Variant being a very popular one. This approach is especially nice if you don't have a type hierarchy (for example when you store primitive types). You would then use a vector type like std::vector<boost::variant<int, char, bool>>
Polymorphism only works through pointers or references. You'll
need the non-template base. Beyond that, you'll need to decide
where the actual objects in container will live. If they're all
static objects (with sufficient lifetime), just using
a std::vector<TemplateInterface*>, and inserting with
v.push_back(&t1);, etc., should do the trick. Otherwise,
you'll probably want to support cloning, and keep clones in the
vector: preferably with Boost pointer containers, but
std::shared_ptr can be used as well.
The solutions given so far are fine though be aware that in case you were returning the template type other than bool in your example , none of these would help as the vtable slots would not be able to be measured before hand. There are actually limits , from a design point of view , for using a template oriented polymorphic solution.
Solution nr. 1
This solution inspired by Sean Parent's C++ Seasoning talk. I highly recommend to check it out on youtube. My solution simplified a bit and the key is to store object in method itself.
One method only
Create a class that will invoke method of stored object.
struct object {
template <class T>
object(T t)
: someFunction([t = std::move(t)]() { return t.someFunction(); })
{ }
std::function<bool()> someFunction;
};
Then use it like this
std::vector<object> v;
// Add classes that has 'bool someFunction()' method
v.emplace_back(someClass());
v.emplace_back(someOtherClass());
// Test our vector
for (auto& x : v)
std::cout << x.someFunction() << std::endl;
Several methods
For several methods use shared pointer to share object between methods
struct object {
template <class T>
object(T&& t) {
auto ptr = std::make_shared<std::remove_reference_t<T>>(std::forward<T>(t));
someFunction = [ptr]() { return ptr->someFunction(); };
someOtherFunction = [ptr](int x) { ptr->someOtherFunction(x); };
}
std::function<bool()> someFunction;
std::function<void(int)> someOtherFunction;
};
Other types
Primitive types (such as int, float, const char*) or classes (std::string etc.) may be wrapped in the same way as object class do but behave differently. For example:
struct otherType {
template <class T>
otherType(T t)
: someFunction([t = std::move(t)]() {
// Return something different
return true;
})
{ }
std::function<bool()> someFunction;
};
So now it is possible to add types that does not have someFunction method.
v.emplace_back(otherType(17)); // Adding an int
v.emplace_back(otherType("test")); // A string
Solution nr. 2
After some thoughts what we basically done in first solution is created array of callable functions. So why not just do the following instead.
// Example class with method we want to put in array
struct myclass {
void draw() const {
std::cout << "myclass" << std::endl;
}
};
// All other type's behaviour
template <class T>
void draw(const T& x) {
std::cout << typeid(T).name() << ": " << x << std::endl;
}
int main()
{
myclass x;
int y = 17;
std::vector<std::function<void()>> v;
v.emplace_back(std::bind(&myclass::draw, &x));
v.emplace_back(std::bind(draw<int>, y));
for (auto& fn : v)
fn();
}
Conclusion
Solution nr. 1 is definitely an interesting method that does not require inheritance nor virtual functions. And can be used to other stuff where you need to store a template argument to be used later.
Solution nr. 2, on the other hand, is simpler, more flexible and probably a better choice here.
If you're looking at a container to store multiple types, then you should explore boost variant from the popular boost library.