Related
Suppose I have some C++ code that looks like this:
class Base {
virtual void dummy() = 0;
// this is to generate a vtable, but note there is no virtual f()
};
class A : public Base {
public:
void f() { /* ... */ };
void dummy() {};
}
class B : public Base {
public:
void f() { /* different implementation from A */ };
void dummy() {};
}
template<class T1, class T2, class T3>
void doStuff(T1 &x, T2 &y, T3 &z) {
for (i=1; i<100000; ++i) {
x.f();
y.f();
z.f();
}
}
The intention here is to avoid virtual function calls to f() during that inner loop, in order to allow compiler optimisations. (This is obviously a simplified version of my actual code. For details of my use case, see this more specific question).
This works fine if the types of doStuff's arguments are known at run-time, but if they're not then it fails:
int main() {
Base *x = new A();
Base *y = new B();
Base *z = new A();
doStuff(*x, *y, *z);
// oops - this instantiates to doStuff(Base &, Base &, Base &)
// and there's no Base::f().
}
to get around this (as suggested by this answer) it seems I have to construct a static dispatch function explicitly:
void doStuff(Base &x, Base &y, Base &z) {
A *a_x = dynamic_cast<A*>(&x);
B *b_x = dynamic_cast<B*>(&x);
A *a_y = dynamic_cast<A*>(&y);
B *b_y = dynamic_cast<B*>(&y);
A *a_z = dynamic_cast<A*>(&z);
B *b_z = dynamic_cast<B*>(&z);
if (a_x && a_y && a_z) {
doStuff(*a_x, &a_y, &a_z);
} else if (a_x && a_y && b_z) {
doStuff(*a_x, &a_y, &b_z);
}
// ... and so on for all eight combinations of A and B.
}
But that's some pretty annoyingly repetitive code, and if I have several functions along the lines of doStuff it will quickly get unmanageable, especially if any of them have four or more arguments.
So my question is, is there any way to avoid this repetitive code? It seems like some further clever use of templates should be able to eliminate it, but I can't quite see how to do it.
The title of your question: "static dispatch" - unfortunately your problem requires finding out the type at runtime... You want to identify the actual type from some base class pointers. This will work only at runtime.
Using dynamic_cast is a hack, the usage of dynamic_cast along usually means bad OO design. BTW, my bet would be that using dynamic_cast (dynamic_cast can be pretty slow!) and then a static function call is slower than simply making f() virtual and putting it to your base class and calling it that way.
Of course your case is a bit more special, you want to perform something else for all 8 cases but this is a piece of dirt work you won't be able to solve elegantly with brief code in C++ in my opinion. It is possible to forge a solution that is less error prone/easy to extend or one that is better in performance but none of them will be brief and/or elegant. Your current doStuff() implementation is rather a less error prone "bulletproof" solution, another one ugly solution has just came to my mind that would have good performance even for a lot of derived classes and class combinations (own type enum with own gettype + switch) but that is ugly as hell.
Summing it up: This problem has no nice solution in C++. You have to rethink your design or you have to live with ugly code when it comes to problems that can not be solved elegantly in C++: for example in case of serialization you often find ugly code like this...
This is a classical multiple-dispatch problem. It's very well developed in the literature. One of the solutions is the Visitor pattern (you need to apply it twice as you have 3 arguments to dispatch on). Another one is a map<tuple<type_info, type_info, type_info>, StuffDoer> (the latter class should have a virtual doStuff method and do a dynamic_cast to all arguments inside).
I have some classes:
class Base
{
public:
virtual void Something() = 0;
}
class A : public Base
{
public:
virtual void Something() { /*...*/ }
void SpecialActionForA();
}
class B : public Base
{
public:
virtual void Something() { /*...*/ }
void SpecialActionForB();
}
and an array:
Base* MyMembers[2];
MyMembers[0] = new A;
MyMembers[1] = new B;
and I want to do:
A* pointer_to_a = Get(0);
B* pointer_to_b = Get(1);
Is there any good way to implement this Get() function?
My solution is:
template <typename T>
T* Get(int index)
{
return dynamic_cast<T*>(MyMembers[index]);
}
But first thing is that I have to write
A* pointer_to_a = Get<A>(0)
Which requires an additional <A>;
Second thing is that if somehow the new is screwed up like:
MyMembers[0] = new B;
Then the Get() is failed.
What I want is something like an automatic mechanism which can maps index 0 to A.
Extra details:
Actually I have 80 different classes derived from Base (They are my User Interfaces),
and my need is to get the real classes (the real UIs) to do things.
The functions I need to use are the above SpecialActionForA()...etc.
The Something() is also used, but is in the initialization stage of these UIs, or something managed by the UI manager system.
You cannot do unknown* Get(int) in principle as it will require two or more functions having the same name but differing only by return value. C++ explicitly prohibits this.
The closest function that you can get is this:
template <typename T> T* Get() {
static T* instance = new T;
return instance;
}
so you will be able to use it as:
A *a = Get<A>();
B *b = Get<B>();
Overloading of function works by looking up the argument list. It is not possible to understand what kind of the value you want by judging only the return type. Thus compiler forces you to give extra detail to instantiate the template. So your options are:
Base *Get(int N) {
return MyMembers[N];
}
or
A *GetA(int N) {
return MyMembers[N];
}
B *GetB(int N) {
return MyMembers[N];
}
or
template <typename T> void Get(int N, T *&item) {
item = (T*)MyMembers[N];
}
A* pointer_to_a;
B* pointer_to_b;
Get(0, pointer_to_a);
Get(1, pointer_to_b);
or your own
template <typename T>
T* Get(int index)
{
return dynamic_cast<T*>(MyMembers[index]);
}
Without knowing your usage scenario, it'll be a bit hard to provide a useful answer, but I actually do believe what you want is type matching. So what you do is that you pass your variables around as Base pointers until I you actually need to know the concrete underlying type, at this point you do a matching on the underlying type of your base pointer. This is works pretty much alike a switch statement mixed with lambdas, I'll try to provide an example.
...
Base* ptr = some_argument;
// Here we need the underlying type, so we'll do a match
Match(ptr)
{
Case(A* a)
{
// this is invoked if ptr happened to hold an A, now do something A specific.
}
Case(B* b)
{
// this is invoked if ptr happened to hold a B, now do something B specific
}
Otherwise()
{
// this is invoked whenever none of the above are
}
}
EndMatch;
...
This is an alternative to the usual solution, which is virtual pointers in the base class, and overriding. Note that type matching is commonly used in functional languages. For C++ there's a cleaver solution to achieving this, by Yuriy Solodkyy one of Bjarne Stroustrup's PhD students.
The short introductury paper can be found here;
https://parasol.tamu.edu/~yuriys/papers/OPM13EA.pdf
For a more information, check out hvis paper, which was presented to the ISO comitee; Open and Efficient Type Switch for C++ by Stroustup, Dos Reis and Solodkyy
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3449.pdf
For the source code behind these papers goto Yuriys homepage at;
https://parasol.tamu.edu/~yuriys/pm/
If the number of classes you've got is truly closed, then consider using closed algebraic data types, as with boost::variant.These are have a few advantages over the unrestricted open algebraic data types, in that the compiler can usually ensure exhaustive matching, and in that the closed nature allows for more optimized pattern matching implementations, though at the cost of flexibility.
Also do note that boost::variant works nicely on C++03!
Do however please consider if you really need pattern matching or polymorphic dispatching. Both approaches are advantages and downsides, the main advance of the pattern matching approach, is that you aren't required to change your classes, and that you avoid polluting your base class with ultra specific virtual methods, which may only be called in a single location.
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.
There's this one thing in C++ which has been making me feel uncomfortable for quite a long time, because I honestly don't know how to do it, even though it sounds simple:
How do I implement Factory Method in C++ correctly?
Goal: to make it possible to allow the client to instantiate some object using factory methods instead of the object's constructors, without unacceptable consequences and a performance hit.
By "Factory method pattern", I mean both static factory methods inside an object or methods defined in another class, or global functions. Just generally "the concept of redirecting the normal way of instantiation of class X to anywhere else than the constructor".
Let me skim through some possible answers which I have thought of.
0) Don't make factories, make constructors.
This sounds nice (and indeed often the best solution), but is not a general remedy. First of all, there are cases when object construction is a task complex enough to justify its extraction to another class. But even putting that fact aside, even for simple objects using just constructors often won't do.
The simplest example I know is a 2-D Vector class. So simple, yet tricky. I want to be able to construct it both from both Cartesian and polar coordinates. Obviously, I cannot do:
struct Vec2 {
Vec2(float x, float y);
Vec2(float angle, float magnitude); // not a valid overload!
// ...
};
My natural way of thinking is then:
struct Vec2 {
static Vec2 fromLinear(float x, float y);
static Vec2 fromPolar(float angle, float magnitude);
// ...
};
Which, instead of constructors, leads me to usage of static factory methods... which essentially means that I'm implementing the factory pattern, in some way ("the class becomes its own factory"). This looks nice (and would suit this particular case), but fails in some cases, which I'm going to describe in point 2. Do read on.
another case: trying to overload by two opaque typedefs of some API (such as GUIDs of unrelated domains, or a GUID and a bitfield), types semantically totally different (so - in theory - valid overloads) but which actually turn out to be the same thing - like unsigned ints or void pointers.
1) The Java Way
Java has it simple, as we only have dynamic-allocated objects. Making a factory is as trivial as:
class FooFactory {
public Foo createFooInSomeWay() {
// can be a static method as well,
// if we don't need the factory to provide its own object semantics
// and just serve as a group of methods
return new Foo(some, args);
}
}
In C++, this translates to:
class FooFactory {
public:
Foo* createFooInSomeWay() {
return new Foo(some, args);
}
};
Cool? Often, indeed. But then- this forces the user to only use dynamic allocation. Static allocation is what makes C++ complex, but is also what often makes it powerful. Also, I believe that there exist some targets (keyword: embedded) which don't allow for dynamic allocation. And that doesn't imply that the users of those platforms like to write clean OOP.
Anyway, philosophy aside: In the general case, I don't want to force the users of the factory to be restrained to dynamic allocation.
2) Return-by-value
OK, so we know that 1) is cool when we want dynamic allocation. Why won't we add static allocation on top of that?
class FooFactory {
public:
Foo* createFooInSomeWay() {
return new Foo(some, args);
}
Foo createFooInSomeWay() {
return Foo(some, args);
}
};
What? We can't overload by the return type? Oh, of course we can't. So let's change the method names to reflect that. And yes, I've written the invalid code example above just to stress how much I dislike the need to change the method name, for example because we cannot implement a language-agnostic factory design properly now, since we have to change names - and every user of this code will need to remember that difference of the implementation from the specification.
class FooFactory {
public:
Foo* createDynamicFooInSomeWay() {
return new Foo(some, args);
}
Foo createFooObjectInSomeWay() {
return Foo(some, args);
}
};
OK... there we have it. It's ugly, as we need to change the method name. It's imperfect, since we need to write the same code twice. But once done, it works. Right?
Well, usually. But sometimes it does not. When creating Foo, we actually depend on the compiler to do the return value optimisation for us, because the C++ standard is benevolent enough for the compiler vendors not to specify when will the object created in-place and when will it be copied when returning a temporary object by value in C++. So if Foo is expensive to copy, this approach is risky.
And what if Foo is not copiable at all? Well, doh. (Note that in C++17 with guaranteed copy elision, not-being-copiable is no problem anymore for the code above)
Conclusion: Making a factory by returning an object is indeed a solution for some cases (such as the 2-D vector previously mentioned), but still not a general replacement for constructors.
3) Two-phase construction
Another thing that someone would probably come up with is separating the issue of object allocation and its initialisation. This usually results in code like this:
class Foo {
public:
Foo() {
// empty or almost empty
}
// ...
};
class FooFactory {
public:
void createFooInSomeWay(Foo& foo, some, args);
};
void clientCode() {
Foo staticFoo;
auto_ptr<Foo> dynamicFoo = new Foo();
FooFactory factory;
factory.createFooInSomeWay(&staticFoo);
factory.createFooInSomeWay(&dynamicFoo.get());
// ...
}
One may think it works like a charm. The only price we pay for in our code...
Since I've written all of this and left this as the last, I must dislike it too. :) Why?
First of all... I sincerely dislike the concept of two-phase construction and I feel guilty when I use it. If I design my objects with the assertion that "if it exists, it is in valid state", I feel that my code is safer and less error-prone. I like it that way.
Having to drop that convention AND changing the design of my object just for the purpose of making factory of it is.. well, unwieldy.
I know that the above won't convince many people, so let's me give some more solid arguments. Using two-phase construction, you cannot:
initialise const or reference member variables,
pass arguments to base class constructors and member object constructors.
And probably there could be some more drawbacks which I can't think of right now, and I don't even feel particularly obliged to since the above bullet points convince me already.
So: not even close to a good general solution for implementing a factory.
Conclusions:
We want to have a way of object instantiation which would:
allow for uniform instantiation regardless of allocation,
give different, meaningful names to construction methods (thus not relying on by-argument overloading),
not introduce a significant performance hit and, preferably, a significant code bloat hit, especially at client side,
be general, as in: possible to be introduced for any class.
I believe I have proven that the ways I have mentioned don't fulfil those requirements.
Any hints? Please provide me with a solution, I don't want to think that this language won't allow me to properly implement such a trivial concept.
First of all, there are cases when
object construction is a task complex
enough to justify its extraction to
another class.
I believe this point is incorrect. The complexity doesn't really matter. The relevance is what does. If an object can be constructed in one step (not like in the builder pattern), the constructor is the right place to do it. If you really need another class to perform the job, then it should be a helper class that is used from the constructor anyway.
Vec2(float x, float y);
Vec2(float angle, float magnitude); // not a valid overload!
There is an easy workaround for this:
struct Cartesian {
inline Cartesian(float x, float y): x(x), y(y) {}
float x, y;
};
struct Polar {
inline Polar(float angle, float magnitude): angle(angle), magnitude(magnitude) {}
float angle, magnitude;
};
Vec2(const Cartesian &cartesian);
Vec2(const Polar &polar);
The only disadvantage is that it looks a bit verbose:
Vec2 v2(Vec2::Cartesian(3.0f, 4.0f));
But the good thing is that you can immediately see what coordinate type you're using, and at the same time you don't have to worry about copying. If you want copying, and it's expensive (as proven by profiling, of course), you may wish to use something like Qt's shared classes to avoid copying overhead.
As for the allocation type, the main reason to use the factory pattern is usually polymorphism. Constructors can't be virtual, and even if they could, it wouldn't make much sense. When using static or stack allocation, you can't create objects in a polymorphic way because the compiler needs to know the exact size. So it works only with pointers and references. And returning a reference from a factory doesn't work too, because while an object technically can be deleted by reference, it could be rather confusing and bug-prone, see Is the practice of returning a C++ reference variable, evil? for example. So pointers are the only thing that's left, and that includes smart pointers too. In other words, factories are most useful when used with dynamic allocation, so you can do things like this:
class Abstract {
public:
virtual void do() = 0;
};
class Factory {
public:
Abstract *create();
};
Factory f;
Abstract *a = f.create();
a->do();
In other cases, factories just help to solve minor problems like those with overloads you have mentioned. It would be nice if it was possible to use them in a uniform way, but it doesn't hurt much that it is probably impossible.
Simple Factory Example:
// Factory returns object and ownership
// Caller responsible for deletion.
#include <memory>
class FactoryReleaseOwnership{
public:
std::unique_ptr<Foo> createFooInSomeWay(){
return std::unique_ptr<Foo>(new Foo(some, args));
}
};
// Factory retains object ownership
// Thus returning a reference.
#include <boost/ptr_container/ptr_vector.hpp>
class FactoryRetainOwnership{
boost::ptr_vector<Foo> myFoo;
public:
Foo& createFooInSomeWay(){
// Must take care that factory last longer than all references.
// Could make myFoo static so it last as long as the application.
myFoo.push_back(new Foo(some, args));
return myFoo.back();
}
};
Have you thought about not using a factory at all, and instead making nice use of the type system? I can think of two different approaches which do this sort of thing:
Option 1:
struct linear {
linear(float x, float y) : x_(x), y_(y){}
float x_;
float y_;
};
struct polar {
polar(float angle, float magnitude) : angle_(angle), magnitude_(magnitude) {}
float angle_;
float magnitude_;
};
struct Vec2 {
explicit Vec2(const linear &l) { /* ... */ }
explicit Vec2(const polar &p) { /* ... */ }
};
Which lets you write things like:
Vec2 v(linear(1.0, 2.0));
Option 2:
you can use "tags" like the STL does with iterators and such. For example:
struct linear_coord_tag linear_coord {}; // declare type and a global
struct polar_coord_tag polar_coord {};
struct Vec2 {
Vec2(float x, float y, const linear_coord_tag &) { /* ... */ }
Vec2(float angle, float magnitude, const polar_coord_tag &) { /* ... */ }
};
This second approach lets you write code which looks like this:
Vec2 v(1.0, 2.0, linear_coord);
which is also nice and expressive while allowing you to have unique prototypes for each constructor.
You can read a very good solution in: http://www.codeproject.com/Articles/363338/Factory-Pattern-in-Cplusplus
The best solution is on the "comments and discussions", see the "No need for static Create methods".
From this idea, I've done a factory. Note that I'm using Qt, but you can change QMap and QString for std equivalents.
#ifndef FACTORY_H
#define FACTORY_H
#include <QMap>
#include <QString>
template <typename T>
class Factory
{
public:
template <typename TDerived>
void registerType(QString name)
{
static_assert(std::is_base_of<T, TDerived>::value, "Factory::registerType doesn't accept this type because doesn't derive from base class");
_createFuncs[name] = &createFunc<TDerived>;
}
T* create(QString name) {
typename QMap<QString,PCreateFunc>::const_iterator it = _createFuncs.find(name);
if (it != _createFuncs.end()) {
return it.value()();
}
return nullptr;
}
private:
template <typename TDerived>
static T* createFunc()
{
return new TDerived();
}
typedef T* (*PCreateFunc)();
QMap<QString,PCreateFunc> _createFuncs;
};
#endif // FACTORY_H
Sample usage:
Factory<BaseClass> f;
f.registerType<Descendant1>("Descendant1");
f.registerType<Descendant2>("Descendant2");
Descendant1* d1 = static_cast<Descendant1*>(f.create("Descendant1"));
Descendant2* d2 = static_cast<Descendant2*>(f.create("Descendant2"));
BaseClass *b1 = f.create("Descendant1");
BaseClass *b2 = f.create("Descendant2");
I mostly agree with the accepted answer, but there is a C++11 option that has not been covered in existing answers:
Return factory method results by value, and
Provide a cheap move constructor.
Example:
struct sandwich {
// Factory methods.
static sandwich ham();
static sandwich spam();
// Move constructor.
sandwich(sandwich &&);
// etc.
};
Then you can construct objects on the stack:
sandwich mine{sandwich::ham()};
As subobjects of other things:
auto lunch = std::make_pair(sandwich::spam(), apple{});
Or dynamically allocated:
auto ptr = std::make_shared<sandwich>(sandwich::ham());
When might I use this?
If, on a public constructor, it is not possible to give meaningful initialisers for all class members without some preliminary calculation, then I might convert that constructor to a static method. The static method performs the preliminary calculations, then returns a value result via a private constructor which just does a member-wise initialisation.
I say 'might' because it depends on which approach gives the clearest code without being unnecessarily inefficient.
Loki has both a Factory Method and an Abstract Factory. Both are documented (extensively) in Modern C++ Design, by Andei Alexandrescu. The factory method is probably closer to what you seem to be after, though it's still a bit different (at least if memory serves, it requires you to register a type before the factory can create objects of that type).
I don't try to answer all of my questions, as I believe it is too broad. Just a couple of notes:
there are cases when object construction is a task complex enough to justify its extraction to another class.
That class is in fact a Builder, rather than a Factory.
In the general case, I don't want to force the users of the factory to be restrained to dynamic allocation.
Then you could have your factory encapsulate it in a smart pointer. I believe this way you can have your cake and eat it too.
This also eliminates the issues related to return-by-value.
Conclusion: Making a factory by returning an object is indeed a solution for some cases (such as the 2-D vector previously mentioned), but still not a general replacement for constructors.
Indeed. All design patterns have their (language specific) constraints and drawbacks. It is recommended to use them only when they help you solve your problem, not for their own sake.
If you are after the "perfect" factory implementation, well, good luck.
This is my c++11 style solution. parameter 'base' is for base class of all sub-classes. creators, are std::function objects to create sub-class instances, might be a binding to your sub-class' static member function 'create(some args)'. This maybe not perfect but works for me. And it is kinda 'general' solution.
template <class base, class... params> class factory {
public:
factory() {}
factory(const factory &) = delete;
factory &operator=(const factory &) = delete;
auto create(const std::string name, params... args) {
auto key = your_hash_func(name.c_str(), name.size());
return std::move(create(key, args...));
}
auto create(key_t key, params... args) {
std::unique_ptr<base> obj{creators_[key](args...)};
return obj;
}
void register_creator(const std::string name,
std::function<base *(params...)> &&creator) {
auto key = your_hash_func(name.c_str(), name.size());
creators_[key] = std::move(creator);
}
protected:
std::unordered_map<key_t, std::function<base *(params...)>> creators_;
};
An example on usage.
class base {
public:
base(int val) : val_(val) {}
virtual ~base() { std::cout << "base destroyed\n"; }
protected:
int val_ = 0;
};
class foo : public base {
public:
foo(int val) : base(val) { std::cout << "foo " << val << " \n"; }
static foo *create(int val) { return new foo(val); }
virtual ~foo() { std::cout << "foo destroyed\n"; }
};
class bar : public base {
public:
bar(int val) : base(val) { std::cout << "bar " << val << "\n"; }
static bar *create(int val) { return new bar(val); }
virtual ~bar() { std::cout << "bar destroyed\n"; }
};
int main() {
common::factory<base, int> factory;
auto foo_creator = std::bind(&foo::create, std::placeholders::_1);
auto bar_creator = std::bind(&bar::create, std::placeholders::_1);
factory.register_creator("foo", foo_creator);
factory.register_creator("bar", bar_creator);
{
auto foo_obj = std::move(factory.create("foo", 80));
foo_obj.reset();
}
{
auto bar_obj = std::move(factory.create("bar", 90));
bar_obj.reset();
}
}
Factory Pattern
class Point
{
public:
static Point Cartesian(double x, double y);
private:
};
And if you compiler does not support Return Value Optimization, ditch it, it probably does not contain much optimization at all...
extern std::pair<std::string_view, Base*(*)()> const factories[2];
decltype(factories) factories{
{"blah", []() -> Base*{return new Blah;}},
{"foo", []() -> Base*{return new Foo;}}
};
I know this question has been answered 3 years ago, but this may be what your were looking for.
Google has released a couple of weeks ago a library allowing easy and flexible dynamic object allocations. Here it is: http://google-opensource.blogspot.fr/2014/01/introducing-infact-library.html
OK here we go. I'm trying to use the CRTP template in order to remove the need of polymorphism from my app. I use an aproach like the one bellow
template <RealType> class Base
{
void doSomething()
{
static_cast<RealType>(this)->doSomethingImpl()
}
class Derived1 : public Base
{
void doSomethingImpl()
{
/* do something, for real */
}
}
class Derived2 : public Base
{
void doSomethingImpl()
{
/* do something else */
}
}
This aproach, if I understood correctly, allows my classes to have no vtable, so function calls are direct and don't require the extra indirection.
Now imagine I want to store all my Derived# classes in a container. Let's say a vector.
First approach : I can create a non-template SuperBase class from which Base inherits and store that in the container.
However it seems to me that if I want to do that, I will have to make doSomething virtual, in SuperBase. And my goal is mainly not to have a vtable.
Second approach : I use type erasure, i.e. something like boost::any to store my elements in the Vector.
But then, I don't see a way I can iterate over the elements and call doSomething on them, because to "use" boost::any, I need to know the real type of the object when iterating.
Do you think what I want to do is even possible ?
Seems to me that it is because doSomething() is part of Base but except using inheritance, I can't see a way to do it ....
And my goal is mainly not to have a vtable.
If you want this, then, unless you implement your own virtual dispatch system (which would likely be inferior to what the compiler does), you're stuck with templates, a.k.a. compile-time polymorphism. And as the name says, in order to use this, everything must be known at compile-time. If you need to make decisions based on runtime events (like, e.g., user input), you want runtime polymorphism.
I can't help but have to ask: Why do you want to avoid vtables? (And if you're so determined, why aren't you programming in C?)
You can do what you want with the proper theoretical operation which is NOT polymorphism, but unification. Most people have no idea what a sum type (discriminated union) is and what it is for which is why they consistently abuse inheritance, which is entirely unrelated.
Unions are more popular in C, for example X-Windows event messages are union based, because they're broken in C++.
A union is the correct way to represent heterogeneous data types as a single type, hence the name unification: it unifies all the components into a single type. Unions always have a finite known number of components, functions using unions invariably use a switch on the discriminant to select the right handler code.
OOP cannot provide unification: it provides subtyping.
Templates provide something quite different again: parametric polymorphism.
All three concepts are quite distinct in both theory and practice. Subtyping OOP style turns out to be the least useful because what it can represent is heavily restricted, however those restrictions do permit dynamic dispatch to an open set of subtypes, which is very nice if it applies to your problem.
So now it is clear, in your array, all you need to put is a union of all your classes, and your problem goes away.
Only .. the classes have to be POD types in C++ at present due to an unprincipled restriction. So the best solution is to use a union of raw C functions, since C function pointers are PODs.
Something like:
enum tag {tag_X, tag_Y};
struct X { int x; };
void px(X a) { cout << a.x; }
struct PX { tag t; X a; void (*p)(X); };
struct Y { double x; };
void py(Y a) { cout << a.x; };
struct PY {tag t; Y a; void (*p)(Y); };
union XY { PX anX; PY anY; };
PX x1 = { tag_X, { 1 }, px };
PY y1 = { tag_Y, { 1.0 }, py };
XY xy1.anPX = x1;
XY xy2.anPy = x2;
XY xys[2] = {xy1, xy1};
xy = xys[0];
switch (xy.anPX.tag) { // hack
case tag_X: xy.anPX.p (xy.PX.x); break;
case tag_Y: xy.anPY.p (xy.PY.x); break;
}
If you think this is ugly, you're right: C and C++ are brain dead. Another solution is to use a tag and a pointer which is cast to a void*, then use the tag to cast to the required type: this is much easier but requires heap allocation of the data and hence you have a memory management issue. Another alternative is Boost variant type (which automates some of the housekeeping but is still very ugly).
Here's similar code in Ocaml:
type xy = X of int | Y of double
let print u =
match u with
| X x -> print_int x
| Y x -> print_double x
in
print (X 1);
print (Y 2.0)
In this code the X and Y are the tags of the C code above, they're called type constructors because they construct an xy type out of an int or a double (resp.). The match expression there is just a switch with automatic selection of the right component type and scoping used to ensure you can't refer to the wrong component (as you could in the C code), also there's no break, match handlers don't drop thru, and the memory management is done by a garbage collector.
You can combine both strengths.
#include <iostream>
struct AnimalBase
{
virtual std::string speak() const = 0;
virtual ~AnimalBase() {};
};
template <typename Derived>
struct Animal : AnimalBase
{
std::string speak() const
{
return static_cast<const Derived*>(this)->speak();
}
};
struct Dog : Animal<Dog>
{
std::string speak() const
{
return "Woof! Woof!";
}
};
struct Cat : Animal<Cat>
{
std::string speak() const
{
return "Meow. Meow.";
}
};
int main()
{
AnimalBase* pets[] = { new Dog, new Cat };
std::cout << Dog().speak() << '\n'
<< Cat().speak() << '\n'
<< pets[0]->speak() << '\n'
<< pets[1]->speak() << std::endl;
delete pets[0];
delete pets[1];
return 0;
}
It's going to be difficult (a hack at best) to hold these objects in a container. You have designed away polymorphism, and yet you seem to really want to use it so you can hold the objects as container<mybaseclass> and use them polymorphically.
It's not clear to me from your posting why you wish to avoid the vtable. If this is for performance, you are probably over-optimizing. Without more background on why you are going this route, it's hard to recommend anything but 'use a base class'.