I have a working interface for two programs (ProgramA and ProgramB) that I would like to improve decoupling both programs as much as possible. The case that I want to cover is making a call from ProgramA to a class from ProgramB (Compute_Prop) that can only be initialized with some arguments which I do not now in advance. Hence, I use a pointer in the header. Currently, I have something like this:
interface.h
#include "programB.h" // loads Compute_Prop
class Compute {
public:
Compute();
Compute(targ1 arg1, targ2 arg2);
~Compute();
// some methods ...
private:
Compute_Prop* compute;
};
interface.cpp
#include "programB.h"
#include "interface.h"
#include "programA.h"
Compute::Compute() = default;
Compute::~Compute() {
delete compute;
}
Compute::Compute(arg1, arg2) {
// do something ... to get data
compute = new Compute_Prop( &data, arg2 );
}
Then, I try to imitate the PIMPL idiom with the following
interface.h
#include "programB.h" // loads Compute_Prop
class Compute {
public:
Compute();
Compute(targ1 arg1, targ2 arg2);
~Compute();
// some methods ...
private:
class PIMPL;
PIMPL* compute;
};
interface.cpp
#include "programB.h"
#include "interface.h"
#include "programA.h"
Compute::PIMPL = Compute_Prop;
Compute::Compute() = default;
Compute::~Compute() {
delete compute;
}
Compute::Compute(arg1, arg2) {
// do something ... to get data
compute = new Compute_Prop( &data, arg2 );
}
but the compiler says:
error: expected unqualified-id
Compute::PIMPL = Compute_Prop;
^
I guess that it has something to do with Compute_Prop not having
an empty constructor. I can't come up with something that works. What should I do? Something like a pointer to a pointer, maybe? As a restriction, I cannot modify programB.
Note: As it is probably already clear from above, my understanding of low level C++/C is scarce.
EDIT: I introduced the corrections suggested by #n.m. and #Matthieu Brucher
Your implementation should use an interface (or in fact a class with only abstract methods) as a base class.
You cannot assign types in C++. You can only create typedefs and aliases, like that:
using PIMPLType = Compute_Prop;
However this won't work in your case.
This is how it should be implemented (also with possibility of multiple implementations):
class IImplementation
{
public:
virtual void saySomething() = 0;
};
class ImplementationA : public IImplementation
{
public:
virtual void saySomething() override {
std::cout << "A";
}
};
class ImplementationB : public IImplementation
{
public:
virtual void saySomething() override {
std::cout << "B";
}
};
class Foo {
IImplementation *pimpl;
public:
Foo()
: pimpl(new ImplementationA)
{}
~Foo() { delete pimpl; }
void saySomething() {
pimpl->saySomething();
}
};
I may have come across a simple solution. I post it here so you can judge if it is adequate, or even if it can be improved --- sure. I am convinced that runtime polymorphism is not needed, not even polymorphism. The member variable compute is going to be a pointer to a Compute_Prop type anyway. Then, given that performance is critical here: why running the extra overhead of virtual member functions?
The point here is to reach an implementation that hides the inclusion of Compute_Prop without loosing performance. How? This particular solution uses a templated class and then explicit instantiation. The point is that instantiation can be done in the implementation. Got it from a Fluent C++ blog post. Also, this post has hints for how the implementation should be done. A prototype would be:
interface.h
template <typename T>
class Compute {
public:
Compute();
Compute(targ1 arg1, targ2 arg2);
~Compute();
// some methods ...
private:
T* compute; // No need to state that is going to be T:=Compute_Prop
};
interface_impl.h
#include "interface.h"
#include "programA.h"
template <typename T>
Compute::Compute() = default;
template <typename T>
Compute::~Compute() {
delete compute;
}
template <typename T>
Compute::Compute(arg1, arg2) {
// do something ... to get data
compute = new T( &data, arg2 );
}
interface.cpp
#include "interface.h"
#include "interface_impl.h"
#include "programA.h"
#include "programB.h" // loads Compute_Prop
int main(int argc, char** argv) {
template class Compute<Compute_Prop>;
}
Another related question that might be useful for those with the same dilemma.
Related
I am just thinking about a way to check an object to be valid in a automated way.
I have a couple of hardware related objects (like class A), which can be deleted by external (physical) events.
To detect this I have used shared/weak pointer. But now I am struggling with the checking of the weak pointer. Since this is done in the same way for each member function for many objects, I am currently searching for a way to do this with less redundant code.
In addition I am writing a library and do not want the user to handle this (simply return the weak pointer to the user to handle it by himself is therefor no option)
My best guess is shown below. My problem is, I could not find a way to generate the member functions (func1, and many more ...) automatically within the template. Doing it by myself would result in lot of redundant code for every member function to be validated (and there are a lot)
Each member function of A (and many more other objects) shall be wrapped by a function doing the validation shown below. This is same for all member functions and done for many classes which can be used as type for the Validator.
Does anyone has an idea how to solve this? Maybe there are other (better) ways to solve this.
Many thanks for your help.
Some constraints:
Only C++11 possible,
No exceptions
class A {
public:
void func1() {}
//many more functions
};
template<typename T>
class Validator
{
//has to be done for all functions of A
void func1()
{
if (!wptr.expired())
{
wptr.lock()->func1();
}
else
errorHandling();
}
private:
std::weak_ptr<T> wptr;
void errorHandling() {}
};
I would protect the full user function call:
class A {
public:
void func1() {}
//many more functions
};
template <typename T>
class Validator
{
public:
#if 1 // template way, but no-expressive signature
template <typename F>
void do_job(F f)
#else // type-erasure way, expressive, but with some overhead
void do_job(std::function<void (T&)> f)
#endif
{
auto t = wptr.lock();
if (t) {
f(*t);
} else {
errorHandling();
}
}
private:
void errorHandling();
private:
std::weak_ptr<T> wptr;
};
So user might chain call:
Validator<A> val;
val.do_job([](A& a)
{
a.func1();
a.func2();
});
If the caller can live with clunky syntax you can use member function pointers:
#include <memory>
#include <iostream>
class A {
public:
void func1() {
std::cout << "hello func1\n";
}
};
template<typename T>
class Validator
{
public:
Validator(std::shared_ptr<T> p) : wptr(p) {}
template <typename MemFun>
void call(MemFun mf) {
if (!wptr.expired())
{
(wptr.lock().get()->*mf)();
}
else
errorHandling();
}
private:
std::weak_ptr<T> wptr;
void errorHandling() {}
};
int main() {
auto x = std::make_shared<A>();
Validator<A> v{x};
v.call(&A::func1);
}
I want to create a library that :-
User adds callback via addCallback<Base>(Callback* callback) (usually at first timestep)
Later, usually in a different .cpp, whenever user call actor<Bx>() :-
if Bx inherit from Base, call callback->callback()
else do nothing
(Information) I know for sure that every Bx always inherit from A.
Here is the initial code :-
#include <iostream>
class A{};
class Callback{
public: virtual void callback()=0;
};
template<class Base> void addCallback(Callback* callback){
//???
};
template<class Bx> void actor(){
//???
}
//^^^^^^ my library end here
class B : public A{};
class B1 : public B{};
class C : public A{};
class CallbackCustom1: public Callback{
public: virtual void callback(){std::cout<<"A"<<std::endl;}
};
class CallbackCustom2: public Callback{
public: virtual void callback(){std::cout<<"B"<<std::endl;}
};
int main(){
CallbackCustom1 call1;
CallbackCustom2 call2;
addCallback<A>(&call1);
addCallback<B>(&call2);
//vvv below is usually in another .cpp
actor<B1>(); // should print "A" and "B"
actor<C>(); // should print "A" only
}
How to do it?
My poor solutions
Solution 1 : std::is_base_of
I really love to use std::is_base_of<Base,Derive>.
However, it is impossible because users want to invoke only a single type Bx in actor<Bx>() for convenience.
std::is_base_of need name of two classes not one.
Solution 2 (MCVE demo) : virtual destructor + std::function
It can be optimized more but I want to keep it simple :-
#include <iostream>
#include <functional>
class A{public: virtual ~A()=default; };
class Callback{
public: virtual void callback()=0;
};
class MyTuple{public:
std::function<bool(A*)> func;
Callback* callback;
};
std::vector<MyTuple> myTuples;
template<class Base> void addCallback(Callback* callback){
std::function<bool(A*)> func=
[](A* a){return dynamic_cast<Base*>(a)!=nullptr;};
MyTuple tuple; tuple.func=func; tuple.callback=callback;
myTuples.push_back(tuple);
}
template<class Bx> void actor(){
Bx b;
for(auto tuple:myTuples){
if(tuple.func(&b)){
tuple.callback->callback();
}
}
}
//^^^^^^ my library end here
It works, but there are some disadvantages :-
I have to add virtual destructor to A to make it polymorphic. I feel that it is a nasty hack.
In my game, in some time-steps, A::~A() is potentially called >100,000 times per seconds.
I can reduce the cost by make B1 and C final and do a batch deletion via derived class, but in some places, it is unsuitable and inconvenient.
I have to create instance of Bx just for the dynamic_cast check.
This may cause some complication if its constructor do something special.
Are there any better way?
Can you require your user to specify the set of allowed Base types? In that case the task becomes simple (online demo):
static_assert(__cplusplus >= 201703L, "example for C++17, but C++14 possible");
#include <iostream>
#include <type_traits>
#include <vector>
struct Callback {
virtual void callback() = 0;
};
template<class... RegisteredBases>
struct CallbackSystem {
template<class Base>
static auto& callbacks_for() {
static std::vector<Callback*> callbacks_for_base_{};
//
// For each `Base`, the callbacks are stored in a different vector.
// This way, we can avoid the in-loop branch (see `actor_impl`).
//
// TODO: consider performance cost of bad memory locality (can be
// improved if necessary).
//
return callbacks_for_base_;
}
template<class Base>
static void addCallback(Callback* callback) {
static_assert((... || std::is_same<Base, RegisteredBases>{}));
callbacks_for<Base>().push_back(callback);
}
template<class Derived, class RegisteredBase>
static void actor_impl() {// called from `actor` for each RegisteredBase
if(std::is_base_of<RegisteredBase, Derived>{}) {// branch outside loop
// if `RegisteredBase` matches then process all its callbacks
for(Callback* callback : callbacks_for<RegisteredBase>()) {
callback->callback();
}
}
}
template<class Derived>
static void actor() {
(actor_impl<Derived, RegisteredBases>(), ...);
}
};
The allowed Base types are registered like this:
using MyCallbacks = CallbackSystem<A, B> {};
The usage reads:
MyCallbacks::addCallback<A>(&call1);
MyCallbacks::addCallback<B>(&call2);
// MyCallbacks::addCallback<B1>(&call2);// compile error (good)
//vvv below is usually in another .cpp
std::cout << R"(should print "A" and "B":)" << std::endl;
MyCallbacks::actor<B1>();
std::cout << R"(should print "A" only:)" << std::endl;
MyCallbacks::actor<C>();
Alternatively, the API can be designed the other way around: Instead of restricting the Base classes one can require the user to specify all classes which are allowed as the template argument of actor.
I have a file: Base.h
class Base;
class DerivedA : public Base;
class DerivedB : public Base;
/*etc...*/
and another file: BaseFactory.h
#include "Base.h"
class BaseFactory
{
public:
BaseFactory(const string &sClassName){msClassName = sClassName;};
Base * Create()
{
if(msClassName == "DerivedA")
{
return new DerivedA();
}
else if(msClassName == "DerivedB")
{
return new DerivedB();
}
else if(/*etc...*/)
{
/*etc...*/
}
};
private:
string msClassName;
};
/*etc.*/
Is there a way to somehow convert this string to an actual type (class), so that BaseFactory wouldn't have to know all the possible Derived classes, and have if() for each one of them? Can I produce a class from this string?
I think this can be done in C# through Reflection. Is there something similar in C++?
Nope, there is none, unless you do the mapping yourself. C++ has no mechanism to create objects whose types are determined at runtime. You can use a map to do that mapping yourself, though:
template<typename T> Base * createInstance() { return new T; }
typedef std::map<std::string, Base*(*)()> map_type;
map_type map;
map["DerivedA"] = &createInstance<DerivedA>;
map["DerivedB"] = &createInstance<DerivedB>;
And then you can do
return map[some_string]();
Getting a new instance. Another idea is to have the types register themself:
// in base.hpp:
template<typename T> Base * createT() { return new T; }
struct BaseFactory {
typedef std::map<std::string, Base*(*)()> map_type;
static Base * createInstance(std::string const& s) {
map_type::iterator it = getMap()->find(s);
if(it == getMap()->end())
return 0;
return it->second();
}
protected:
static map_type * getMap() {
// never delete'ed. (exist until program termination)
// because we can't guarantee correct destruction order
if(!map) { map = new map_type; }
return map;
}
private:
static map_type * map;
};
template<typename T>
struct DerivedRegister : BaseFactory {
DerivedRegister(std::string const& s) {
getMap()->insert(std::make_pair(s, &createT<T>));
}
};
// in derivedb.hpp
class DerivedB {
...;
private:
static DerivedRegister<DerivedB> reg;
};
// in derivedb.cpp:
DerivedRegister<DerivedB> DerivedB::reg("DerivedB");
You could decide to create a macro for the registration
#define REGISTER_DEC_TYPE(NAME) \
static DerivedRegister<NAME> reg
#define REGISTER_DEF_TYPE(NAME) \
DerivedRegister<NAME> NAME::reg(#NAME)
I'm sure there are better names for those two though. Another thing which probably makes sense to use here is shared_ptr.
If you have a set of unrelated types that have no common base-class, you can give the function pointer a return type of boost::variant<A, B, C, D, ...> instead. Like if you have a class Foo, Bar and Baz, it looks like this:
typedef boost::variant<Foo, Bar, Baz> variant_type;
template<typename T> variant_type createInstance() {
return variant_type(T());
}
typedef std::map<std::string, variant_type (*)()> map_type;
A boost::variant is like an union. It knows which type is stored in it by looking what object was used for initializing or assigning to it. Have a look at its documentation here. Finally, the use of a raw function pointer is also a bit oldish. Modern C++ code should be decoupled from specific functions / types. You may want to look into Boost.Function to look for a better way. It would look like this then (the map):
typedef std::map<std::string, boost::function<variant_type()> > map_type;
std::function will be available in the next version of C++ too, including std::shared_ptr.
No there isn't. My preferred solution to this problem is to create a dictionary which maps name to creation method. Classes that want to be created like this then register a creation method with the dictionary. This is discussed in some detail in the GoF patterns book.
The short answer is you can't. See these SO questions for why:
Why does C++ not have reflection?
How can I add reflection to a C++ application?
I have answered in another SO question about C++ factories. Please see there if a flexible factory is of interest. I try to describe an old way from ET++ to use macros which has worked great for me.
ET++ was a project to port old MacApp to C++ and X11. In the effort of it Eric Gamma etc started to think about Design Patterns
boost::functional has a factory template which is quite flexible: http://www.boost.org/doc/libs/1_54_0/libs/functional/factory/doc/html/index.html
My preference though is to generate wrapper classes which hide the mapping and object creation mechanism. The common scenario I encounter is the need to map different derived classes of some base class to keys, where the derived classes all have a common constructor signature available. Here is the solution I've come up with so far.
#ifndef GENERIC_FACTORY_HPP_INCLUDED
//BOOST_PP_IS_ITERATING is defined when we are iterating over this header file.
#ifndef BOOST_PP_IS_ITERATING
//Included headers.
#include <unordered_map>
#include <functional>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition.hpp>
//The GENERIC_FACTORY_MAX_ARITY directive controls the number of factory classes which will be generated.
#ifndef GENERIC_FACTORY_MAX_ARITY
#define GENERIC_FACTORY_MAX_ARITY 10
#endif
//This macro magic generates GENERIC_FACTORY_MAX_ARITY + 1 versions of the GenericFactory class.
//Each class generated will have a suffix of the number of parameters taken by the derived type constructors.
#define BOOST_PP_FILENAME_1 "GenericFactory.hpp"
#define BOOST_PP_ITERATION_LIMITS (0,GENERIC_FACTORY_MAX_ARITY)
#include BOOST_PP_ITERATE()
#define GENERIC_FACTORY_HPP_INCLUDED
#else
#define N BOOST_PP_ITERATION() //This is the Nth iteration of the header file.
#define GENERIC_FACTORY_APPEND_PLACEHOLDER(z, current, last) BOOST_PP_COMMA() BOOST_PP_CAT(std::placeholders::_, BOOST_PP_ADD(current, 1))
//This is the class which we are generating multiple times
template <class KeyType, class BasePointerType BOOST_PP_ENUM_TRAILING_PARAMS(N, typename T)>
class BOOST_PP_CAT(GenericFactory_, N)
{
public:
typedef BasePointerType result_type;
public:
virtual ~BOOST_PP_CAT(GenericFactory_, N)() {}
//Registers a derived type against a particular key.
template <class DerivedType>
void Register(const KeyType& key)
{
m_creatorMap[key] = std::bind(&BOOST_PP_CAT(GenericFactory_, N)::CreateImpl<DerivedType>, this BOOST_PP_REPEAT(N, GENERIC_FACTORY_APPEND_PLACEHOLDER, N));
}
//Deregisters an existing registration.
bool Deregister(const KeyType& key)
{
return (m_creatorMap.erase(key) == 1);
}
//Returns true if the key is registered in this factory, false otherwise.
bool IsCreatable(const KeyType& key) const
{
return (m_creatorMap.count(key) != 0);
}
//Creates the derived type associated with key. Throws std::out_of_range if key not found.
BasePointerType Create(const KeyType& key BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N,const T,& a)) const
{
return m_creatorMap.at(key)(BOOST_PP_ENUM_PARAMS(N,a));
}
private:
//This method performs the creation of the derived type object on the heap.
template <class DerivedType>
BasePointerType CreateImpl(BOOST_PP_ENUM_BINARY_PARAMS(N,const T,& a))
{
BasePointerType pNewObject(new DerivedType(BOOST_PP_ENUM_PARAMS(N,a)));
return pNewObject;
}
private:
typedef std::function<BasePointerType (BOOST_PP_ENUM_BINARY_PARAMS(N,const T,& BOOST_PP_INTERCEPT))> CreatorFuncType;
typedef std::unordered_map<KeyType, CreatorFuncType> CreatorMapType;
CreatorMapType m_creatorMap;
};
#undef N
#undef GENERIC_FACTORY_APPEND_PLACEHOLDER
#endif // defined(BOOST_PP_IS_ITERATING)
#endif // include guard
I am generally opposed to heavy macro use, but I've made an exception here. The above code generates GENERIC_FACTORY_MAX_ARITY + 1 versions of a class named GenericFactory_N, for each N between 0 and GENERIC_FACTORY_MAX_ARITY inclusive.
Using the generated class templates is easy. Suppose you want a factory to create BaseClass derived objects using a string mapping. Each of the derived objects take 3 integers as constructor parameters.
#include "GenericFactory.hpp"
typedef GenericFactory_3<std::string, std::shared_ptr<BaseClass>, int, int int> factory_type;
factory_type factory;
factory.Register<DerivedClass1>("DerivedType1");
factory.Register<DerivedClass2>("DerivedType2");
factory.Register<DerivedClass3>("DerivedType3");
factory_type::result_type someNewObject1 = factory.Create("DerivedType2", 1, 2, 3);
factory_type::result_type someNewObject2 = factory.Create("DerivedType1", 4, 5, 6);
The GenericFactory_N class destructor is virtual to allow the following.
class SomeBaseFactory : public GenericFactory_2<int, BaseType*, std::string, bool>
{
public:
SomeBaseFactory() : GenericFactory_2()
{
Register<SomeDerived1>(1);
Register<SomeDerived2>(2);
}
};
SomeBaseFactory factory;
SomeBaseFactory::result_type someObject = factory.Create(1, "Hi", true);
delete someObject;
Note that this line of the generic factory generator macro
#define BOOST_PP_FILENAME_1 "GenericFactory.hpp"
Assumes the generic factory header file is named GenericFactory.hpp
Detail solution for registering the objects, and accessing them with string names.
common.h:
#ifndef COMMON_H_
#define COMMON_H_
#include<iostream>
#include<string>
#include<iomanip>
#include<map>
using namespace std;
class Base{
public:
Base(){cout <<"Base constructor\n";}
virtual ~Base(){cout <<"Base destructor\n";}
};
#endif /* COMMON_H_ */
test1.h:
/*
* test1.h
*
* Created on: 28-Dec-2015
* Author: ravi.prasad
*/
#ifndef TEST1_H_
#define TEST1_H_
#include "common.h"
class test1: public Base{
int m_a;
int m_b;
public:
test1(int a=0, int b=0):m_a(a),m_b(b)
{
cout <<"test1 constructor m_a="<<m_a<<"m_b="<<m_b<<endl;
}
virtual ~test1(){cout <<"test1 destructor\n";}
};
#endif /* TEST1_H_ */
3. test2.h
#ifndef TEST2_H_
#define TEST2_H_
#include "common.h"
class test2: public Base{
int m_a;
int m_b;
public:
test2(int a=0, int b=0):m_a(a),m_b(b)
{
cout <<"test1 constructor m_a="<<m_a<<"m_b="<<m_b<<endl;
}
virtual ~test2(){cout <<"test2 destructor\n";}
};
#endif /* TEST2_H_ */
main.cpp:
#include "test1.h"
#include "test2.h"
template<typename T> Base * createInstance(int a, int b) { return new T(a,b); }
typedef std::map<std::string, Base* (*)(int,int)> map_type;
map_type mymap;
int main()
{
mymap["test1"] = &createInstance<test1>;
mymap["test2"] = &createInstance<test2>;
/*for (map_type::iterator it=mymap.begin(); it!=mymap.end(); ++it)
std::cout << it->first << " => " << it->second(10,20) << '\n';*/
Base *b = mymap["test1"](10,20);
Base *b2 = mymap["test2"](30,40);
return 0;
}
Compile and Run it (Have done this with Eclipse)
Output:
Base constructor
test1 constructor m_a=10m_b=20
Base constructor
test1 constructor m_a=30m_b=40
Tor Brede Vekterli provides a boost extension that gives exactly the functionality you seek. Currently, it is slightly awkward fitting with current boost libs, but I was able to get it working with 1.48_0 after changing its base namespace.
http://arcticinteractive.com/static/boost/libs/factory/doc/html/factory/factory.html#factory.factory.reference
In answer to those who question why such a thing (as reflection) would be useful for c++ - I use it for interactions between the UI and an engine - the user selects an option in the UI, and the engine takes the UI selection string, and produces an object of the desired type.
The chief benefit of using the framework here (over maintaining a fruit-list somewhere) is that the registering function is in each class's definition (and only requires one line of code calling the registration function per registered class) - as opposed to a file containing the fruit-list, which must be manually added to each time a new class is derived.
I made the factory a static member of my base class.
Meaning reflection as in Java.
there is some info here:
http://msdn.microsoft.com/en-us/library/y0114hz2(VS.80).aspx
Generally speaking, search google for "c++ reflection"
This is the factory pattern. See wikipedia (and this example). You cannot create a type per se from a string without some egregious hack. Why do you need this?
Yes, it is possible, without the use of frameworks and macros, just getting the memory address of the class methods and constructors. You can retrieve them from the map generated by the linker, when configured for this action.
visit this site
https://ealaframework.no-ip.org/wiki/page/c.reference
A C++11-style full example:
// Base.h
class Base;
class DerivedA : public Base;
class DerivedB : public Base;
// BaseFactory.h
class BaseFactory
{
public:
static BaseFactory& get() {
static BaseFactory singleton;
return singleton;
}
virtual ~BaseFactory() {};
BaseFactory(const BaseFactory&) = delete;
BaseFactory(BaseFactory&&) = delete;
template <class DerivedClass>
static std::shared_ptr<Base> creator()
{
return std::shared_ptr<Base>(new DerivedClass());
}
template <class DerivedClass>
void register_class(const std::string& class_name)
{
if (name_to_creator_map.find(class_name) == name_to_creator_map.end())
{
std::function<std::shared_ptr<Base>(void)> functor = &BaseFactory::template creator<DerivedClass>;
name_to_creator_map.emplace(class_name, functor);
}
}
std::shared_ptr<Base> create(const std::string& class_name) const;
private:
BaseFactory();
std::map<std::string, std::function<std::shared_ptr<Base>(void)>> name_to_creator_map;
};
// example.cpp using BaseFactory
BaseFactory::get().register_class<DerivedA>("DerivedA");
BaseFactory::get().register_class<DerivedB>("DerivedB");
auto a_obj = BaseFactory::get().create("DerivedA");
auto b_obj = BaseFactory::get().create("DerivedB");
There is a ready-to-use reflection library https://www.rttr.org/ . You can easily instantiate class by string with it.
struct MyStruct { MyStruct() {}; void func(double) {}; int data; };
RTTR_REGISTRATION
{
registration::class_<MyStruct>("MyStruct")
.constructor<>()
.property("data", &MyStruct::data)
.method("func", &MyStruct::func);
}
type t = type::get_by_name("MyStruct");
variant var = t.create();
I need several C++ classes to have a static method "register", however the implementation of register varies between those classes.
It should be static because my idea is to "register" all those classes with Lua (only once of course).
Obviously I can't declare an interface with a static pure virtual function. What do you guys suggest me to do ? Simplicity is welcome, but I think some kind of template could work.
Example of what I would like to achieve
class registerInterface
{
public:
static virtual void register() = 0; //obviously illegal
};
class someClass: public registerInterface
{
static virtual void register()
{
//I register myself with Lua
}
}
class someOtherClass: public registerInterface
{
static virtual void register()
{
//I register myself with Lua in a different way
}
}
int main()
{
someClass::register();
someOtherClass::register();
return 0;
}
Based on how you've described the problem, it's unclear to me why you even need the 'virtual static method' on the classes. This should be perfectly legal.
class SomeClass {
static void register(void) {
...
}
}
class SomeOtherClass {
static void register(void) {
...
}
}
int main(int argc, char* argv[]) {
SomeClass::register();
SomeOtherClass::register();
return 0;
}
Drop the RegisterInterface, I don't think you need it.
If it helps, you could take Hitesh's answer, and add:
struct luaRegisterManager {
template <typename T>
void registrate() {
T::registrate();
// do something else to record the fact that we've registered -
// perhaps "registrate" should be returning some object to help with that
}
};
Then:
int main() {
luaRegisterManager lrm;
lrm.registrate<someClass>();
lrm.registrate<someOtherClass>();
}
More generally, if you want to introduce any dynamic polymorphism in C++, then you need an object, not just a class. So again, perhaps the various register functions should be returning objects, with some common interface base class registeredClass, or classRegistrationInfo, or something along those lines.
Could provide an example of what you feel it is that you need dynamic polymorphism for? Hitesh's code precisely matches your one example, as far as I can see, so that example must not cover all of your anticipated use cases. If you write the code that would be using it, perhaps it will become clear to you how to implement it, or perhaps someone can advise.
Something else that might help:
#include <iostream>
#include <string>
#include <vector>
struct Registered {
virtual std::string name() = 0;
virtual ~Registered() {}
Registered() {
all.push_back(this);
}
static std::vector<Registered*> all;
};
std::vector<Registered*> Registered::all;
typedef std::vector<Registered*>::iterator Iter;
template <typename T>
struct RegisteredT : Registered {
std::string n;
RegisteredT(const std::string &name) : n(name) { T::registrate(); }
std::string name() { return n; }
// other functions here could be implemented in terms of calls to static
// functions of T.
};
struct someClass {
static Registered *r;
static void registrate() { std::cout << "registering someClass\n"; }
};
Registered *someClass::r = new RegisteredT<someClass>("someClass");
struct someOtherClass {
static Registered *r;
static void registrate() { std::cout << "registering someOtherClass\n"; }
};
Registered *someOtherClass::r = new RegisteredT<someOtherClass>("someOtherClass");
int main() {
for (Iter it = Registered::all.begin(); it < Registered::all.end(); ++it) {
std::cout << (*it)->name() << "\n";
}
}
There are all sorts of problems with this code if you try to split it across multiple compilation units. Furthermore, this kind of thing leads to spurious reports from memory leak detectors unless you also write some code to tear everything down at the end, or use a vector of shared_ptr, Boost pointer vector, etc. But you see the general idea that a class can "register itself", and that you need an object to make virtual calls.
In C++ you usually try to avoid static initialisation, though, in favour of some sort of setup / dependency injection at the start of your program. So normally you would just list all the classes you care about (calling a function on each one) rather than try to do this automatically.
Your intentions are noble, but your solution is inkling towards "overengineering" (unless I am missing an obvious solution).
Here is one possibility: You can use the Virtual Friend function idiom For example,
class RegisterInterface{
friend void register(RegisterInterface* x){x->do_real_register();}
protected:
virtual void do_real_register();
}
class Foo : public RegisterInterface{
protected:
virtual void do_real_register(){}
};
class Bar : public RegisterInterface{
protected:
virtual void do_real_register(){}
};
int main(int argc, char* argv[]) {
BOOST_FOREACH(RegisterInterface* ri, registered_interfaces)
{
register(ri);
}
return 0;
}
I know you've already accepted an answer, but I figured I would write this up anyway. You can have self-registering classes if you use some static initialization and the CRTP:
#include <vector>
#include <iostream>
using namespace std;
class RegisterableRoot // Holds the list of functions to call, doesn't actually need
// need to be a class, could just be a collection of globals
{
public:
typedef void (*registration_func)();
protected:
static std::vector<registration_func> s_registery;
public:
static void do_registration()
{
for(int i = 0; i < s_registery.size(); ++i)
s_registery[i]();
}
static bool add_func(registration_func func) // returns something so we can use it in
// in an initializer
{
s_registery.push_back(func);
return true;
}
};
template<typename RegisterableType> // Doesn't really need to inherit from
class Registerable : public RegisterableRoot // RegisterableRoot
{
protected:
static const bool s_effect;
};
class A : public Registerable<A> // Honestly, neither does A need to inherit from
// Registerable<T>
{
public:
static void Register()
{
cout << "A" << endl;
}
};
class B : public Registerable<B>
{
public:
static void Register()
{
cout << "B" << endl;
}
};
int main()
{
RegisterableRoot::do_registration();
return 0;
}
std::vector<RegisterableRoot::registration_func> RegisterableRoot::s_registery;
template <typename RegisterableType> // This is the "cute" part, we initialize the
// static s_effect so we build the list "magically"
const bool Registerable<RegisterableType>::s_effect = add_func(&RegisterableType::Register);
template class Registerable<A>; // Explicitly instantiate the template
// causes the equivalent of
// s_registery.push_back(&A::Register) to
// be executed
template class Registerable<B>;
This outputs
A
B
although I wouldn't rely on this order if I were you. Note that the template class Registerable<X> need not be in the same translation unit as the call to do_registration, you can put it with the rest of your definition of Foo. If you inherit from Registerable<> and you don't write a static void Register() function for your class you'll get a (admittedly probably cryptic) compiler error much like you might expect if there really was such a thing as "static virtuals". The "magic" merely adds the class specific function to the list to be called, this avoids several of the pitfalls of doing the actual registration in a static initializer. You still have to call do_registration for anything to happen.
How about this way? Define an interface class:
// IFoobar.h
class IFoobar{
public:
virtual void Register(void) = 0;
}
Then define the class that handles the register..
// RegisterFoobar.h
class RegisterFoobar{
public:
// Constructors etc...
IFoobar* fooBar;
static void RegisterFoobar(IFoobar& fubar){
foobar = &fubar;
}
private:
void Raise(void){ foobar->Register(); }
}
Now, then define another class like this
// MyFuBar.h
class MyFuBar : IFoobar{
public:
// Constructors etc...
void Register(void);
private:
RegisterFoobar* _regFoobar;
}
Call the code like this:
//MyFuBar.cpp
MyFuBar::MyFuBar(){
_regFoobar = new Foobar();
_regFoobar->RegisterFoobar(this);
}
void MyFuBar::Register(void){
// Raised here...
}
Maybe I have misunderstood your requirements...
I have an abstract base class like so:
class AbstractBaseClass
{};
a templated concrete class that derives from it:
template<class T>
class ConcreteClass : public AbstractBaseClass
{
public:
ConcreteClass(T input) : data(input) {}
private:
T data;
};
AndI have a factory class that creates AbstractBaseClasses
class MyFactory
{
public:
boost::shared_ptr<AbstractBaseClass> CreateBlah();
boost::shared_ptr<AbstractBaseClass> CreateFoo();
template<class T>
boost::shared_ptr<AbstractBaseClass> Create(T input)
{
return boost::shared_ptr<AbstractBaseClass>(new ConcreteClass<T>(input));
}
};
The problem with this, is that now EVERYTHING that uses MyFactory has to include the entire implementation to ConcreteClass. Ideally, I want nothing but MyFactory to know about ConcreteClass.
Is there any way to architect this to achieve this goal? (Besides manually making a new Create function in MyFactory for every type I want instead of templating it).
you'll need to put the factory implementation into the implementation file (which you mentioned you'd like to avoid, but it is the lesser evil unless the interfaces are small, and/or your projects are small).
of course, there are a few other ways you could approach this, such as putting the implementation into base classes, and making derived bases factories, or using some other really weird template syntax to reduce instantiations in dependent translations. this really comes down to convenience and scale for your project. if you are working on one or more large projects, then full abstraction wrt instantiation will serve your needs best in the long run (assuming you need dynamic polymorphism and memory).
you may also try other approaches (such as overloading) to reduce errors by using type-safety.
the short answer is that you'll really need to abstract the interfaces/instantiation into one or multiple implementation files to remove header dependencies - very common idiom, and many ways to tackle it. you can over course further divide and use polymorphism for your factories as well.
you may also use template forward declarations to minimize the sets to the compilation unit. provided:
/** in MyIntermediateFactory.hpp */
class MyIntermediateFactory {
public:
static template<class T> boost::shared_ptr<T> Create(float);
};
/** in Concrete.hpp */
template<Concrete>
boost::shared_ptr<T> MyIntermediateFactory::Create<Concrete>(float arg) {
/* … */
}
using this you can select portions of programs/interfaces which you need in the library, then wrap it all up in a real Factory (for the build at hand). the linker/instantiation should fail along the way if you actually attempt to request a creation which is not visible.
there a lot of options, really - you need to figure out how big your scale is in order to determine what to abstract (or not). instantiation requires interface, to remove header dependencies, you'll have to abstract the instantiation someplace.
My approach to the same problem in the past was the creation of a set of concrete factories (one per type) that get registered in the global factory (for illustration purposes, indexing by object name):
class AbstractBaseClass;
class ConcreteFactory
{
public:
AbstractBaseClass * create();
};
class AbstractFactory
{
public:
void registerFactory( std::string const & name, std::shared_ptr<ConcreteFactory> const & f )
{
factory[ name ] = f; // check for collisions, complain if so ...
}
AbstractBaseClass * create( std::string const & name )
{
return factory[name]->create(); // check for existence before dereferencing...
}
private:
std::map<std::string, std::shared_ptr<ConcreteFactory> > factory;
};
I used this in a piece of code that was heavily templated to reduce compilation time. Each concrete factory and the class that it creates need only be in a single translation unit that registers the concrete factory. The rest of the code only need to use the common interface to AbstractBaseClass.
I realize I am answering this five years later. Maybe the language has grown a tad since then. I'd like to offer something that seems right, if I understand the question properly, if for no other point than to help others who might find this question and wonder what they could do.
factory.hpp
#include "base.hpp"
namespace tvr
{
namespace test
{
class factory
{
public:
typedef base::ptr Ptr;
enum eSpecial
{
eDerived
};
template<typename Type>
Ptr create()
{
Ptr result;
result.reset(new Type());
return result;
}
template<typename Type, typename DataType>
Ptr create(const DataType& data)
{
Ptr result;
result.reset(new Type(data));
return result;
}
template<typename Type, typename DataType>
Ptr create(const DataType& data, eSpecial tag)
{
Ptr result;
result.reset(new Type());
static_cast<Type*>(result.get())->set_item(data);
return result;
}
};
}
}
base.hpp
#include <memory>
namespace tvr
{
namespace test
{
class base
{
public:
typedef std::shared_ptr<base> ptr;
public:
base() {}
virtual ~base() {}
virtual void do_something() = 0;
};
}
}
some_class.hpp
#include <ostream>
namespace tvr
{
namespace test
{
struct some_class
{
};
}
}
std::ostream& operator<<(std::ostream& out, const tvr::test::some_class& item)
{
out << "This is just some class.";
return out;
}
template_derived.hpp
#include <iostream>
#include "base.hpp"
namespace tvr
{
namespace test
{
template<typename Type>
class template_derived : public base
{
public:
template_derived(){}
virtual ~template_derived(){}
virtual void do_something()
{
std::cout << "Doing something, like printing _item as \"" << _item << "\"." << std::endl;
}
void set_item(const Type data)
{
_item = data;
}
private:
Type _item;
};
}
}
and, finally, main.cpp
#include <vector>
#include "base.hpp"
#include "factory.hpp"
namespace tvr
{
namespace test
{
typedef std::vector<tvr::test::base::ptr> ptr_collection;
struct iterate_collection
{
void operator()(const ptr_collection& col)
{
for (ptr_collection::const_iterator iter = col.begin();
iter != col.end();
++iter)
{
iter->get()->do_something();
}
}
};
}
}
#include "template_derived.hpp"
#include "some_class.hpp"
namespace tvr
{
namespace test
{
inline int test()
{
ptr_collection items;
tvr::test::factory Factory;
typedef template_derived<unsigned int> UIntConcrete;
typedef template_derived<double> DoubleConcrete;
typedef template_derived<std::string> StringConcrete;
typedef template_derived<some_class> SomeClassConcrete;
items.push_back(Factory.create<SomeClassConcrete>(some_class(), tvr::test::factory::eDerived));
for (unsigned int i = 5; i < 7; ++i)
{
items.push_back(Factory.create<UIntConcrete>(i, tvr::test::factory::eDerived));
}
items.push_back(Factory.create<DoubleConcrete>(4.5, tvr::test::factory::eDerived));
items.push_back(Factory.create<StringConcrete>(std::string("Hi there!"), tvr::test::factory::eDerived));
iterate_collection DoThem;
DoThem(items);
return 0;
}
}
}
int main(int argc, const char* argv[])
{
tvr::test::test();
}
output
Doing something, like printing _item as "This is just some class.".
Doing something, like printing _item as "5".
Doing something, like printing _item as "6".
Doing something, like printing _item as "4.5".
Doing something, like printing _item as "Hi there!".
This uses a combination of templates, function overloading, and tagging through enums to help create a flexible factory class that doesn't require knowing much about the individual classes it instantiates, to include templated concrete classes as the OP asked about.
The 'eDerived' tag (in the form of an enum) tells the compiler to use the version of the factory's create function that takes a class like the template_derived class, which has a function that allows me to assign data to one of its members. As you can tell from the way I ordered the headers in main.cpp, the factory doesn't know anything about template_derived. Neither does the function calling the base class's virtual function (do_something). I think this is what the OP wanted, but without having to add a various create functions within every class that this factory might generate.
I also showed how one doesn't have to explicitly create functions for each class the factory should create. The factory's overloaded create functions can create anything derived from the base class that matches the appropriate signature.
I didn't do an extensive performance analysis on this code, but I did enough to see that the majority of the work happens in the streaming operator. This compiles in about 1 second on my 3.30Ghz quad core machine. You might need to experiment with more robust code to see how badly it might bog down the compiler, if much at all.
I've tested this code in VC++ 2015, although it probably works in other compilers pretty easily. If you want to copy this, you'll need to add your own guard headers. In any event, I hope this is useful.
You could use explicit template instanciation. Trying to call the factory method with a template parameter not explicit instanciated will give you a linker error. Note the explicit template instanciation in MyFactory.cpp
template AbstractBaseClass* MyFactory::Create(int input);
All put together looks like this (I removed shared_ptr for the sake of simplicity):
Main.cpp:
#include "AbstractBaseClass.h"
#include "MyFactory.h"
//we do not need to know nothing about concreteclass (neither MyFactory.h includes it)
int main()
{
MyFactory f;
AbstractBaseClass* ab = f.Create(10);
ab = f.Create(10.0f);
return 0;
}
MyFactory.h:
#include "AbstractBaseClass.h"
class MyFactory
{
public:
template<class T>
AbstractBaseClass* Create(T input);
};
MyFactory.cpp:
#include "MyFactory.h"
#include "ConcreteClass.h"
template<class T>
AbstractBaseClass* MyFactory::Create(T input) {
return new ConcreteClass<T>(input);
}
//explicit template instanciation
template AbstractBaseClass* MyFactory::Create(int input);
//you could use as well specialisation for certain types
template<>
AbstractBaseClass* MyFactory::Create(float input) {
return new ConcreteClass<float>(input);
}
AbstractBaseClass.h:
class AbstractBaseClass{};
ConcreteClass.h:
#include "AbstractBaseClass.h"
template<class T>
class ConcreteClass : public AbstractBaseClass
{
public:
ConcreteClass(T input) : data(input) {}
private:
T data;
};
You're looking for the "PIMPL" idiom. There's a good explanation at Herb Sutter's GOTW site
It can't be done because ConcreteClass is a template, that means you need the complete implementation available at compile time. Same reason why you can't precompile templates and have to write them all in header files instead.