If I store a polymorphic functor in an std::function, is there a way to extract the functor without knowing the concrete type?
Here is a simplified version of the code:
struct Base {
//...
virtual int operator()(int foo) const = 0;
void setBar(int bar){}
};
struct Derived : Base {
//...
int operator()(int foo) const override {}
};
std::function<int(int)> getFunction() {
return Derived();
}
int main() {
auto f = getFunction();
// How do I call setBar() ?
if (Base* b = f.target<Base>()) {} // Fails: returns nullptr
else if(Derived* d = f.target<Derived>()) {
d->setBar(5); // Works but requires Derived type
}
std::cout << f(7) << std::endl;
return 0;
}
I want the client to be able to provide their own function, and for my handler to use the functionality of the Base if it's available.
The fall back would be of course to just use the abstract base class instead of std::function and clients would implement the ABC interface as they would have pre-C++11:
std::shared_ptr<Base> getFunction {
return std::make_shared<Derived>();
}
but I wanted to know if it's possible to create a more flexible and easier to use interface with C++14. It seems all that's missing is a cast inside std::function::target
It seems all that's missing is a cast inside std::function::target
All target<T> currently needs is to check target_id<T> == stored_type_info.
Being able to cast back to the real (erased) type in a context where that type may not be visible, and then check how it's related to the requested type ... is not really feasible.
Anyway, std::function is polymorphic only on the function signature. That's the thing it abstracts. If you want general-purpose polymorphism, just return a unique_ptr<Base> and use that.
If you really want function<int(int)> for the function-call syntax, instantiate it with a pimpl wrapper for unique_ptr<Base>.
Possible solution would be to have a thin wrapper:
struct BaseCaller {
BaseCaller( std::unique_ptr<Base> ptr ) : ptr_( std::move( ptr ) ) {}
int operator()( int foo ) { return (*ptr)( foo ); }
std::unique_ptr<Base> ptr_;
};
now user must create all derived from Base classed through this wrapper:
std::function<int(int)> getFunction() {
return BaseCaller( std::make_unique<Derived>() );
}
and you check in your call that target is a BaseCaller.
I want the client to be able to provide their own function, and for my handler to use the functionality of the Base if it's available.
The main drawback to using virtual dispatch is that it may create an optimization barrier. For instance, the virtual function calls cannot usually be inlined, and "devirtualization" optimizations are generally pretty difficult for the compiler to actually do in practical situations.
If you are in a situation where the code is performance critical, you can roll your own type-erasure and avoid any vtable / dynamic allocations.
I'm going to follow a pattern demonstrated in an old (but well-known) article, the "Impossibly Fast Delegates".
// Represents a pointer to a class implementing your interface
class InterfacePtr {
using ObjectPtr = void*;
using CallOperator_t = int(*)(ObjectPtr, int);
using SetBar_t = void(ObjectPtr, int);
ObjectPtr obj_;
CallOperator_t call_;
SetBar_t set_bar_;
// Ctor takes any type that implements your interface,
// stores pointer to it as void * and lambda functions
// that undo the cast and forward the call
template <typename T>
InterfacePtr(T * t)
: obj_(static_cast<ObjectPtr>(t))
, call_(+[](ObjectPtr ptr, int i) { return (*static_cast<T*>(ptr))(i); })
, set_bar_(+[](ObjectPtr ptr, int i) { static_cast<T*>(ptr)->set_bar(i); })
{}
int operator()(int i) {
return call_(obj_, i);
}
void set_bar()(int i) {
return set_bar_(obj_, i);
}
};
Then, you would take InterfacePtr instead of a pointer to Base in your API.
If you want the interface member set_bar to be optional, then you could use SFINAE to detect whether set_bar is present, and have two versions of the constructor, one for when it is, and one for when it isn't. There is recently a really great exposition of the "detection idiom" at various C++ standards on Tartan Llama's blog, here. The advantage of that would be that you get something similar to what virtual gives you, with the possibility to optionally override functions, but the dispatch decisions get made at compile-time, and you aren't forced to have a vtable. And all of the functions can potentially be inlined if the optimizer can prove to itself that e.g. in some compilation unit using this, only one type is actually passed to your API through this mechanism.
A difference is that this InterfacePtr is non-owning and doesn't have the dtor or own the storage of the object it's pointing to.
If you want InterfacePtr to be owning, like std::function, and copy the functor into its own memory and take care of deleting it when it goes out of scope, then I'd recommend to use std::any to represent the object instead of void *, and use std::any_cast in the lambdas instead of static_cast<T*> in my implementation. There's some good further discussion of std::any and why it's good for this usecase on /r/cpp here.
I don't think there's any way to do what you were originally asking, and recover the "original" functor type from std::function. Type erasure erases the type, you can't get it back without doing something squirrelly.
Edit: Another alternative you might consider is to use a type-erasure library like dyno
std::function<X>::target<T> can only cast back to exactly T*.
This is because storing how to convert to every type that can be converted to T* would require storing more information. It takes information to convert a pointer-to-derived to a pointer-to-base in the general case in C++.
target is intended to simply permit replacing some function-pointer style machinery with std::functions and have the existing machinery work, and do so with nearly zero cost (just compare typeids). Extending that cost to every base type of the stored type would have been hard, so it wasn't done, and won't be free, so it probably won't be done in the future.
std::function is, however, just an example of type erasure, and you can roll your own with additional functionality.
The first thing I'd do is I would do away with your virtual operator(). Type-erasure based polymorphism doesn't need that.
The second thing is get your hands on an any -- either boost::any or c++17's std::any.
That writes the hard part of type erasure -- small buffer optimization and value storage -- for you.
Add to that your own dispatch table.
template<class Sig>
struct my_extended_function;
template<class R, class...Args>
struct my_extended_function<R(Args...)> {
struct vtable {
R(*f)(any&, Args&&...) = 0;
void*(*cast)(any&, std::type_info const&) = 0;
};
template<class...Bases, class T>
my_extended_function make_with_bases( T t ) {
return {
get_vtable<T, Bases...>(),
std::move(t)
};
}
R operator()(Args...args)const {
return (*p_vtable->f)(state, std::forward<Args>(args)...);
}
private:
template<class T, class...Bases>
static vtable make_vtable() {
vtable ret{
// TODO: R=void needs different version
+[](any& ptr, Args&&...args)->R {
return (*any_cast<T*>(ptr))(std::forward<Args>(args)...);
},
+[](any& ptr, std::type_info const& tid)->void* {
T* pt = any_cast<T*>(ptr);
if (typeid(pt)==tid) return pt;
// TODO: iterate over Bases, see if any match tid
// implicitly cast pt to the Bases* in question, and return it.
}
};
}
template<class T, class...Bases>
vtable const* get_vtable() {
static vtable const r = make_vtable<T,Bases...>();
return &r;
}
vtable const* p_vtable = nullptr;
mutable std::any state;
my_extended_function( vtable const* vt, std::any s ):
p_vtable(vt),
state(std::move(s))
{}
};
Related
I wrote my own "slot" aka "callable wrapper" because I wanted to provide member function slot rebinding on other objects (i.e. I needed a way to store the member function pointer and a pointer to the class in question).
I ran a small size test and discovered std::function on my system (64-bit Linux) was twice (GCC/libstdc++) to three times (Clang/libc++) the size of my own implementation of a similar class, with a size of 16 bytes. The implementation for non-member functions and lambda's goes like this (the const void* first argument is for uniformity with member function slots not shown here):
template<typename... ArgTypes>
class slot
{
public:
virtual ~slot() = default;
virtual void operator()(const void* object, ArgTypes...) const = 0;
protected:
slot() = default;
};
template<typename Callable, typename... ArgTypes>
class callable_slot : public slot<ArgTypes...>
{
public:
callable_slot(Callable function_pointer_or_lambda) : callable(function_pointer_or_lambda) {}
virtual void operator()(const void*, ArgTypes... args) const override { callable(args...); }
private:
Callable callable;
};
template<typename Callable>
class callable_slot<Callable> : public slot<>
{
public:
callable_slot(Callable function_pointer_or_lambda) : callable(function_pointer_or_lambda) {}
virtual void operator()(const void*) const override { callable(); }
private:
Callable callable;
};
template<typename Callable, typename... ArgTypes>
using function_slot = callable_slot<Callable, ArgTypes...>;
I understand things like target aren't implemented here, but I don't think any of the missing functions increase the size of the object.
What I'm asking is: why is std::function larger in size than my cheap implementation above?
Your function_slot takes a Callable and set of args..., and returns a type inheriting from slot<args...> with a virtual operator().
To use it polymorphically as a value, you'd have to wrap it in a smart pointer and store it on the heap, and you'd have to forward the wrapping classes operator() to the slot<args...> one.
std::function corresponds to that wrapper, not to your slot or callable_slot object.
template<class...Args>
struct smart_slot {
template<class Callable> // add SFINAE tests here TODO! IMPORTANT!
smart_slot( Callable other ):
my_slot( std::make_unique<callable_slot<Callable, Args...>>( std::move(other) ) )
{}
void operator()( Args...args ) const {
return (*my_slot)(std::forward<Args>(args)...);
}
// etc
private:
std::unique_ptr<slot<Args...>> my_slot;
};
smart_slot is closer to std::function than your code. As far as std::function is concerned, everything you wrote is an implementation detail that users of std::function wouldn't ever see.
Now, this would only require that std::function be the size of one pointer. std::function is larger because it has what is known as small object optimization.
Instead of just storing a smart pointer, it has a block of memory within itself. If the object you pass in fits in that block of memory, it constructs it in-place that block of memory instead of doing a heap allocation.
std::function is basically mandated to do this for simple cases like being passed a function pointer. Quality implementations do it for larger and more complex objects. MSVC does it for objects up to the size of two std::strings.
This means if you do this:
std::function<void(std::ostream&)> hello_world =
[s = "hello world"s](std::ostream& os)
{
os << s;
};
hello_world(std::cout);
it does no dynamic allocation on a decent implementation of std::function.
Note that some major library vendors do dynamic allocation in this case.
Your class functionality is very different from the one provided by std::function. You request users of your class to provide the actual type of 'callable' object as an argument of the template.
On the contrary, std::function does not require this, and can deal with any callable object, as long as it has operator() with required interface. Try using your template with an object of unknown type, for example, a result of std::bind, and you will know what I mean.
Since the functionality is very different, comparison of sizes is moot.
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;
}
So, I have something along the lines of these structs:
struct Generic {}
struct Specific : Generic {}
At some point I have the the need to downcast, ie:
Specific s = (Specific) GetGenericData();
This is a problem because I get error messages stating that no user-defined cast was available.
I can change the code to be:
Specific s = (*(Specific *)&GetGenericData())
or using reinterpret_cast, it would be:
Specific s = *reinterpret_cast<Specific *>(&GetGenericData());
But, is there a way to make this cleaner? Perhaps using a macro or template?
I looked at this post C++ covariant templates, and I think it has some similarities, but not sure how to rewrite it for my case. I really don't want to define things as SmartPtr. I would rather keep things as the objects they are.
It looks like GetGenericData() from your usage returns a Generic by-value, in which case a cast to Specific will be unsafe due to object slicing.
To do what you want to do, you should make it return a pointer or reference:
Generic* GetGenericData();
Generic& GetGenericDataRef();
And then you can perform a cast:
// safe, returns nullptr if it's not actually a Specific*
auto safe = dynamic_cast<Specific*>(GetGenericData());
// for references, this will throw std::bad_cast
// if you try the wrong type
auto& safe_ref = dynamic_cast<Specific&>(GetGenericDataRef());
// unsafe, undefined behavior if it's the wrong type,
// but faster if it is
auto unsafe = static_cast<Specific*>(GetGenericData());
I assume here that your data is simple.
struct Generic {
int x=0;
int y=0;
};
struct Specific:Generic{
int z=0;
explicit Specific(Generic const&o):Generic(o){}
// boilerplate, some may not be needed, but good habit:
Specific()=default;
Specific(Specific const&)=default;
Specific(Specific &&)=default;
Specific& operator=(Specific const&)=default;
Specific& operator=(Specific &&)=default;
};
and bob is your uncle. It is somewhat important that int z hae a default initializer, so we don't have to repeat it in the from-parent ctor.
I made thr ctor explicit so it will be called only explicitly, instead of by accident.
This is a suitable solution for simple data.
So the first step is to realize you have a dynamic state problem. The nature of the state you store changes based off dynamic information.
struct GenericState { virtual ~GenericState() {} }; // data in here
struct Generic;
template<class D>
struct GenericBase {
D& self() { return *static_cast<D&>(*this); }
D const& self() const { return *static_cast<D&>(*this); }
// code to interact with GenericState here via self().pImpl
// if you have `virtual` behavior, have a non-virtual method forward to
// a `virtual` method in GenericState.
};
struct Generic:GenericBase<Generic> {
// ctors go here, creates a GenericState in the pImpl below, or whatever
~GenericState() {} // not virtual
private:
friend struct GenericBase<Generic>;
std::unique_ptr<GenericState> pImpl;
};
struct SpecificState : GenericState {
// specific stuff in here, including possible virtual method overrides
};
struct Specific : GenericBase<Specific> {
// different ctors, creates a SpecificState in a pImpl
// upcast operators:
operator Generic() && { /* move pImpl into return value */ }
operator Generic() const& { /* copy pImpl into return value */ }
private:
friend struct GenericBase<Specific>;
std::unique_ptr<SpecificState> pImpl;
};
If you want the ability to copy, implement a virtual GenericState* clone() const method in GenericState, and in SpecificState override it covariantly.
What I have done here is regularized the type (or semiregularized if we don't support move). The Specific and Generic types are unrelated, but their back end implementation details (GenericState and SpecificState) are related.
Interface duplication is avoided mostly via CRTP and GenericBase.
Downcasting now can either involve a dynamic check or not. You go through the pImpl and cast it over. If done in an rvalue context, it moves -- if in an lvalue context, it copies.
You could use shared pointers instead of unique pointers if you prefer. That would permit non-copy non-move based casting.
Ok, after some additional study, I am wondering if what is wrong with doing this:
struct Generic {}
struct Specific : Generic {
Specific( const Generic &obj ) : Generic(obj) {}
}
Correct me if I am wrong, but this works using the implicit copy constructors.
Assuming that is the case, I can avoid having to write one and does perform the casting automatically, and I can now write:
Specific s = GetGenericData();
Granted, for large objects, this is probably not a good idea, but for smaller ones, will this be a "correct" solution?
I have a number of unrelated types that all support the same operations through overloaded free functions (ad hoc polymorphism):
struct A {};
void use(int x) { std::cout << "int = " << x << std::endl; }
void use(const std::string& x) { std::cout << "string = " << x << std::endl; }
void use(const A&) { std::cout << "class A" << std::endl; }
As the title of the question implies, I want to store instances of those types in an heterogeneous container so that I can use() them no matter what concrete type they are. The container must have value semantics (ie. an assignment between two containers copies the data, it doesn't share it).
std::vector<???> items;
items.emplace_back(3);
items.emplace_back(std::string{ "hello" });
items.emplace_back(A{});
for (const auto& item: items)
use(item);
// or better yet
use(items);
And of course this must be fully extensible. Think of a library API that takes a vector<???>, and client code that adds its own types to the already known ones.
The usual solution is to store (smart) pointers to an (abstract) interface (eg. vector<unique_ptr<IUsable>>) but this has a number of drawbacks -- from the top of my head:
I have to migrate my current ad hoc polymorphic model to a class hierarchy where every single class inherits from the common interface. Oh snap! Now I have to write wrappers for int and string and what not... Not to mention the decreased reusability/composability due to the free member functions becoming intimately tied to the interface (virtual member functions).
The container loses its value semantics: a simple assignment vec1 = vec2 is impossible if we use unique_ptr (forcing me to manually perform deep copies), or both containers end up with shared state if we use shared_ptr (which has its advantages and disadvantages -- but since I want value semantics on the container, again I am forced to manually perform deep copies).
To be able to perform deep copies, the interface must support a virtual clone() function which has to be implemented in every single derived class. Can you seriously think of something more boring than that?
To sum it up: this adds a lot of unnecessary coupling and requires tons of (arguably useless) boilerplate code. This is definitely not satisfactory but so far this is the only practical solution I know of.
I have been searching for a viable alternative to subtype polymorphism (aka. interface inheritance) for ages. I play a lot with ad hoc polymorphism (aka. overloaded free functions) but I always hit the same hard wall: containers have to be homogeneous, so I always grudgingly go back to inheritance and smart pointers, with all the drawbacks already listed above (and probably more).
Ideally, I'd like to have a mere vector<IUsable> with proper value semantics, without changing anything to my current (absence of) type hierarchy, and keep ad hoc polymorphism instead of requiring subtype polymorphism.
Is this possible? If so, how?
Different alternatives
It is possible. There are several alternative approaches to your problem. Each one has different advantages and drawbacks (I will explain each one):
Create an interface and have a template class which implements this interface for different types. It should support cloning.
Use boost::variant and visitation.
Blending static and dynamic polymorphism
For the first alternative you need to create an interface like this:
class UsableInterface
{
public:
virtual ~UsableInterface() {}
virtual void use() = 0;
virtual std::unique_ptr<UsableInterface> clone() const = 0;
};
Obviously, you don't want to implement this interface by hand everytime you have a new type having the use() function. Therefore, let's have a template class which does that for you.
template <typename T> class UsableImpl : public UsableInterface
{
public:
template <typename ...Ts> UsableImpl( Ts&&...ts )
: t( std::forward<Ts>(ts)... ) {}
virtual void use() override { use( t ); }
virtual std::unique_ptr<UsableInterface> clone() const override
{
return std::make_unique<UsableImpl<T>>( t ); // This is C++14
// This is the C++11 way to do it:
// return std::unique_ptr<UsableImpl<T> >( new UsableImpl<T>(t) );
}
private:
T t;
};
Now you can actually already do everything you need with it. You can put these things in a vector:
std::vector<std::unique_ptr<UsableInterface>> usables;
// fill it
And you can copy that vector preserving the underlying types:
std::vector<std::unique_ptr<UsableInterface>> copies;
std::transform( begin(usables), end(usables), back_inserter(copies),
[]( const std::unique_ptr<UsableInterface> & p )
{ return p->clone(); } );
You probably don't want to litter your code with stuff like this. What you want to write is
copies = usables;
Well, you can get that convenience by wrapping the std::unique_ptr into a class which supports copying.
class Usable
{
public:
template <typename T> Usable( T t )
: p( std::make_unique<UsableImpl<T>>( std::move(t) ) ) {}
Usable( const Usable & other )
: p( other.clone() ) {}
Usable( Usable && other ) noexcept
: p( std::move(other.p) ) {}
void swap( Usable & other ) noexcept
{ p.swap(other.p); }
Usable & operator=( Usable other )
{ swap(other); }
void use()
{ p->use(); }
private:
std::unique_ptr<UsableInterface> p;
};
Because of the nice templated contructor you can now write stuff like
Usable u1 = 5;
Usable u2 = std::string("Hello usable!");
And you can assign values with proper value semantics:
u1 = u2;
And you can put Usables in an std::vector
std::vector<Usable> usables;
usables.emplace_back( std::string("Hello!") );
usables.emplace_back( 42 );
and copy that vector
const auto copies = usables;
You can find this idea in Sean Parents talk Value Semantics and Concepts-based Polymorphism. He also gave a very brief version of this talk at Going Native 2013, but I think this is to fast to follow.
Moreover, you can take a more generic approach than writing your own Usable class and forwarding all the member functions (if you want to add other later). The idea is to replace the class Usable with a template class. This template class will not provide a member function use() but an operator T&() and operator const T&() const. This gives you the same functionality, but you don't need to write an extra value class every time you facilitate this pattern.
A safe, generic, stack-based discriminated union container
The template class boost::variant is exactly that and provides something like a C style union but safe and with proper value semantics. The way to use it is this:
using Usable = boost::variant<int,std::string,A>;
Usable usable;
You can assign from objects of any of these types to a Usable.
usable = 1;
usable = "Hello variant!";
usable = A();
If all template types have value semantics, then boost::variant also has value semantics and can be put into STL containers. You can write a use() function for such an object by a pattern that is called the visitor pattern. It calls the correct use() function for the contained object depending on the internal type.
class UseVisitor : public boost::static_visitor<void>
{
public:
template <typename T>
void operator()( T && t )
{
use( std::forward<T>(t) );
}
}
void use( const Usable & u )
{
boost::apply_visitor( UseVisitor(), u );
}
Now you can write
Usable u = "Hello";
use( u );
And, as I already mentioned, you can put these thingies into STL containers.
std::vector<Usable> usables;
usables.emplace_back( 5 );
usables.emplace_back( "Hello world!" );
const auto copies = usables;
The trade-offs
You can grow the functionality in two dimensions:
Add new classes which satisfy the static interface.
Add new functions which the classes must implement.
In the first approach I presented it is easier to add new classes. The second approach makes it easier to add new functionality.
In the first approach it it impossible (or at least hard) for client code to add new functions. In the second approach it is impossible (or at least hard) for client code to add new classes to the mix. A way out is the so-called acyclic visitor pattern which makes it possible for clients to extend a class hierarchy with new classes and new functionality. The drawback here is that you have to sacrifice a certain amount of static checking at compile-time. Here's a link which describes the visitor pattern including the acyclic visitor pattern along with some other alternatives. If you have questions about this stuff, I'm willing to answer.
Both approaches are super type-safe. There is not trade-off to be made there.
The run-time-costs of the first approach can be much higher, since there is a heap allocation involved for each element you create. The boost::variant approach is stack based and therefore is probably faster. If performance is a problem with the first approach consider to switch to the second.
Credit where it's due: When I watched Sean Parent's Going Native 2013 "Inheritance Is The Base Class of Evil" talk, I realized how simple it actually was, in hindsight, to solve this problem. I can only advise you to watch it (there's much more interesting stuff packed in just 20 minutes, this Q/A barely scratches the surface of the whole talk), as well as the other Going Native 2013 talks.
Actually it's so simple it hardly needs any explanation at all, the code speaks for itself:
struct IUsable {
template<typename T>
IUsable(T value) : m_intf{ new Impl<T>(std::move(value)) } {}
IUsable(IUsable&&) noexcept = default;
IUsable(const IUsable& other) : m_intf{ other.m_intf->clone() } {}
IUsable& operator =(IUsable&&) noexcept = default;
IUsable& operator =(const IUsable& other) { m_intf = other.m_intf->clone(); return *this; }
// actual interface
friend void use(const IUsable&);
private:
struct Intf {
virtual ~Intf() = default;
virtual std::unique_ptr<Intf> clone() const = 0;
// actual interface
virtual void intf_use() const = 0;
};
template<typename T>
struct Impl : Intf {
Impl(T&& value) : m_value(std::move(value)) {}
virtual std::unique_ptr<Intf> clone() const override { return std::unique_ptr<Intf>{ new Impl<T>(*this) }; }
// actual interface
void intf_use() const override { use(m_value); }
private:
T m_value;
};
std::unique_ptr<Intf> m_intf;
};
// ad hoc polymorphic interface
void use(const IUsable& intf) { intf.m_intf->intf_use(); }
// could be further generalized for any container but, hey, you get the drift
template<typename... Args>
void use(const std::vector<IUsable, Args...>& c) {
std::cout << "vector<IUsable>" << std::endl;
for (const auto& i: c) use(i);
std::cout << "End of vector" << std::endl;
}
int main() {
std::vector<IUsable> items;
items.emplace_back(3);
items.emplace_back(std::string{ "world" });
items.emplace_back(items); // copy "items" in its current state
items[0] = std::string{ "hello" };
items[1] = 42;
items.emplace_back(A{});
use(items);
}
// vector<IUsable>
// string = hello
// int = 42
// vector<IUsable>
// int = 3
// string = world
// End of vector
// class A
// End of vector
As you can see, this is a rather simple wrapper around a unique_ptr<Interface>, with a templated constructor that instantiates a derived Implementation<T>. All the (not quite) gory details are private, the public interface couldn't be any cleaner: the wrapper itself has no member functions except construction/copy/move, the interface is provided as a free use() function that overloads the existing ones.
Obviously, the choice of unique_ptr means that we need to implement a private clone() function that is called whenever we want to make a copy of an IUsable object (which in turn requires a heap allocation). Admittedly one heap allocation per copy is quite suboptimal, but this is a requirement if any function of the public interface can mutate the underlying object (ie. if use() took non-const references and modified them): this way we ensure that every object is unique and thus can freely be mutated.
Now if, as in the question, the objects are completely immutable (not only through the exposed interface, mind you, I really mean the whole objects are always and completely immutable) then we can introduce shared state without nefarious side effects. The most straightforward way to do this is to use a shared_ptr-to-const instead of a unique_ptr:
struct IUsableImmutable {
template<typename T>
IUsableImmutable(T value) : m_intf(std::make_shared<const Impl<T>>(std::move(value))) {}
IUsableImmutable(IUsableImmutable&&) noexcept = default;
IUsableImmutable(const IUsableImmutable&) noexcept = default;
IUsableImmutable& operator =(IUsableImmutable&&) noexcept = default;
IUsableImmutable& operator =(const IUsableImmutable&) noexcept = default;
// actual interface
friend void use(const IUsableImmutable&);
private:
struct Intf {
virtual ~Intf() = default;
// actual interface
virtual void intf_use() const = 0;
};
template<typename T>
struct Impl : Intf {
Impl(T&& value) : m_value(std::move(value)) {}
// actual interface
void intf_use() const override { use(m_value); }
private:
const T m_value;
};
std::shared_ptr<const Intf> m_intf;
};
// ad hoc polymorphic interface
void use(const IUsableImmutable& intf) { intf.m_intf->intf_use(); }
// could be further generalized for any container but, hey, you get the drift
template<typename... Args>
void use(const std::vector<IUsableImmutable, Args...>& c) {
std::cout << "vector<IUsableImmutable>" << std::endl;
for (const auto& i: c) use(i);
std::cout << "End of vector" << std::endl;
}
Notice how the clone() function has disappeared (we don't need it any more, we just share the underlying object and it's no bother since it's immutable), and how copy is now noexcept thanks to shared_ptr guarantees.
The fun part is, the underlying objects have to be immutable, but you can still mutate their IUsableImmutable wrapper so it's still perfectly OK to do this:
std::vector<IUsableImmutable> items;
items.emplace_back(3);
items[0] = std::string{ "hello" };
(only the shared_ptr is mutated, not the underlying object itself so it doesn't affect the other shared references)
Maybe boost::variant?
#include <iostream>
#include <string>
#include <vector>
#include "boost/variant.hpp"
struct A {};
void use(int x) { std::cout << "int = " << x << std::endl; }
void use(const std::string& x) { std::cout << "string = " << x << std::endl; }
void use(const A&) { std::cout << "class A" << std::endl; }
typedef boost::variant<int,std::string,A> m_types;
class use_func : public boost::static_visitor<>
{
public:
template <typename T>
void operator()( T & operand ) const
{
use(operand);
}
};
int main()
{
std::vector<m_types> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(std::string("hello"));
vec.push_back(A());
for (int i=0;i<4;++i)
boost::apply_visitor( use_func(), vec[i] );
return 0;
}
Live example: http://coliru.stacked-crooked.com/a/e4f4ccf6d7e6d9d8
The other answers earlier (use vtabled interface base class, use boost::variant, use virtual base class inheritance tricks) are all perfectly good and valid solutions for this problem, each with a difference balance of compile time versus run time costs. I would suggest though that instead of boost::variant, on C++ 11 and later use eggs::variant instead which is a reimplementation of boost::variant using C++ 11/14 and it is enormously superior on design, performance, ease of use, power of abstraction and it even provides a fairly full feature subset on VS2013 (and a full feature set on VS2015). It's also written and maintained by a lead Boost author.
If you are able to redefine the problem a bit though - specifically, that you can lose the type erasing std::vector in favour of something much more powerful - you could use heterogenous type containers instead. These work by returning a new container type for each modification of the container, so the pattern must be:
newtype newcontainer=oldcontainer.push_back(newitem);
These were a pain to use in C++ 03, though Boost.Fusion makes a fair fist of making them potentially useful. Actually useful usability is only possible from C++ 11 onwards, and especially so from C++ 14 onwards thanks to generic lambdas which make working with these heterogenous collections very straightforward to program using constexpr functional programming, and probably the current leading toolkit library for that right now is proposed Boost.Hana which ideally requires clang 3.6 or GCC 5.0.
Heterogeneous type containers are pretty much the 99% compile time 1% run time cost solution. You'll see a lot of compiler optimiser face plants with current compiler technology e.g. I once saw clang 3.5 generate 2500 opcodes for code which should have generated two opcodes, and for the same code GCC 4.9 spat out 15 opcodes 12 of which didn't actually do anything (they loaded memory into registers and did nothing with those registers). All that said, in a few years time you will be able to achieve optimal code generation for heterogeneous type containers, at which point I would expect they'll become the next gen form of C++ metaprogramming where instead of arsing around with templates we'll be able to functionally program the C++ compiler using actual functions!!!
Heres an idea I got recently from std::function implementation in libstdc++:
Create a Handler<T> template class with a static member function that knows how to copy, delete and perform other operations on T.
Then store a function pointer to that static functon in the constructor of your Any class. Your Any class doesn't need to know about T then, it just needs this function pointer to dispatch the T-specific operations. Notice that the signature of the function is independant of T.
Roughly like so:
struct Foo { ... }
struct Bar { ... }
struct Baz { ... }
template<class T>
struct Handler
{
static void action(Ptr data, EActions eAction)
{
switch (eAction)
{
case COPY:
call T::T(...);
case DELETE:
call T::~T();
case OTHER:
call T::whatever();
}
}
}
struct Any
{
Ptr handler;
Ptr data;
template<class T>
Any(T t)
: handler(Handler<T>::action)
, data(handler(t, COPY))
{}
Any(const Any& that)
: handler(that.handler)
, data(handler(that.data, COPY))
{}
~Any()
{
handler(data, DELETE);
}
};
int main()
{
vector<Any> V;
Foo foo; Bar bar; Baz baz;
v.push_back(foo);
v.push_back(bar);
v.push_back(baz);
}
This gives you type erasure while still maintaining value semantics, and does not require modification of the contained classes (Foo, Bar, Baz), and doesn't use dynamic polymorphism at all. It's pretty cool stuff.
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.