Linking to dynamically available functions at compile time - c++

Suppose I have the following core class:
class Core {
public:
template<typename T>
void accept(T object);
}
I now want to be able to write methods like this:
void handle(int par);
and register them somewhere during linking/compiling stage and call the correct method registered for some typename in the Core.accept(T) method. For example calling
Core.accept(5) would hand 5 over to the handle(int) function after it is somehow registered. Something like this (not compilable example):
template<typename T>
void Core::accept(T par) {
// constexpr std::map<std::type_info, Function> type_func_mapping;
auto it = type_func_mapping.get(typeid(T)); // Should be constexpr
static_assert (it != type_func_mapping.end(), "No handler found for typename " + typeid(T).name())
auto function = *it; // Also constexpr
function(par);
}
Are there any problems with this approach/does exist a better one?
Note: I want to be able to extract the sources of class Core in a way that I can store them in a read-only header/source file and don't even have to touch them again.

You could use pointer to functions to store the registered function.
static void (*reg_func)(args);
static void register(void (*func)(args)){
reg_func = func;
}
//registration part
register(handle);
//function call inside accept,use can use some sanity checks also
reg_func(5 or whatever)
With this you don't have to touch your core class or even the file containing the core class. You can define the handle function in some other file but take care of visibility mode of handle function. Your handle function will register itself and then accept can call the registered function.

Related

Set class methods as functions defined externally

I am implementing a hashtable, and I have written the following (fragment of a) class definition:
template <typename KEY, typename VAL>
class ExtendibleHashTable {
/* Main hash function used. Initially, the identity function. */
size_t hash(KEY key) {
return key;
}
I want to further add a public method, that allows one to set a custom hash function. I do know about function pointers, so I tried something like this (underneath, in the same class definition):
/* Set new hash. */
void set_hash(size_t new_hash(KEY)) {
this -> hash = new_hash;
}
However, this does not compile.
Can you tell me the best way to achieve this effect? I have looked at the <functional> header but it doesn't seem to be the answer I need (or maybe I haven't understood its purpose).
You cannot replace member functions dynamically in C++. Nor can you dynamically add member functions.
You can, however, have a class that contains function pointers or std:: function objects that you can change at run-time. So, you could for example do something like this:
class ExtendibleHashTable {
private:
std::function<size_t (KEY)> m_hash_func;
public:
size_t hash(KEY key) {
if (m_hash_func) {
return m_hash_func(key);
}
return key;
}
void set_hash(const std::function<size_t (KEY)>& func) {
m_hash_func = func;
}
};
In the above, the hash function will by default just return key if no specific function has been set. But, if set_hash has been called with an appropriate hash function (free standing function, function object or lambda), then it will instead call that function and return its result.

metaprogramming with variadic templates in C++

I am working on a simple game engine that provides a base class for game objects that can be extended with subclasses for the specific game. I need to write a function that can take a file, parse object names from it, and instantiate the corresponding objects in the game; providing a mechanism for storing level data in files. I had hoped to use metaprogramming to create a function that allows the caller to pass in a variable number of data types and generates a function that searches for names corresponding to those types in a file. Its use would look something along the lines of this (using templates):
fileParseFunction<type1, type2 type3>("filename");
would generate a function equivalent to:
fileParseFunction(string filename)
{
//code that opens file called "filename" and handles tokenizing/parsing
if(token == "type1")
{
gameWorld.add(new type1());
}
elseif(token == "type2")
{
gameWorld.add(new type2());
}
elseif(token == "type3")
{
gameWorld.add(new type3());
}
//other code to finish loading the level
}
Called with the parameter "filename". This should work for a variable number of types (3 in the example). I wrote some code to test the concept which involves generating a similar function. It uses templates to convert typename symbols to strings (this is needed for use in the comparisons in the function I eventually hope to write) and also variadic templates to generate a function that prints the names of all the types passed in as template parameters. Here it is:
#define TypeNameTemplate(a) template<> inline const char* typeName<a>(void) { return #a; }
template <typename T>
inline const char* typeName(void) { return "unknown"; }
TypeNameTemplate(int);
TypeNameTemplate(std::string);
TypeNameTemplate(double);
TypeNameTemplate(bool);
TypeNameTemplate(float);
/*template <>
inline const char* typeName<int>(void) { return "int"; }*/
template <typename T> inline void printtypes()
{
std::cout << typeName<T>();
}
template <typename T, typename... Args> void printtypes()
{
std::cout << typeName<T>() << std::endl;
printtypes<Args...>();
}
using namespace std;
int main()
{
//string a = typeName<int>();
//print();
printtypes<int, double, string, bool, float>();
return 0;
}
printtypes() should generate a function equivalent to:
void printtypes()
{
std::cout << typeName<int>();
std::cout << typeName<std:string>();
std::cout << typeName<double>();
std::cout << typeName<bool>();
std::cout << typeName<float>();
}
However, during compilation i get this error:
E:\C++ projects\templateTest\main.cpp:26:5: note: candidates are:
E:\C++ projects\templateTest\main.cpp:18:35: note: void printtypes() [with T = float]
E:\C++ projects\templateTest\main.cpp:23:46: note: void printtypes() [with T = float; Args = {}]
It appears that upon reaching the end up the variadic parameter pack recursively, the compiler does not know whether to call the template specialized on only one type with the last type in the pack, or the variadic template with the last type in the pack plus an empty parameter pack. Is what I'm attempting to do possible/practical in C++, and is there a way to let the compiler know that it should use the singe parameter template for the base/final case of the recursive call?
A simple solution is to add another explicit parameter to the second overload:
template <typename T, typename T2, typename... Args> void printtypes()
{
std::cout << typeName<T>() << std::endl;
printtypes<T2,Args...>();
}
While this answer does not answer your specific question about variadic templates, I hope it does answer your underlying question about how to make your game engine extensible.
What you came up with by creating your fileParseFunction() is an implementation of the Factory Method pattern. This is the main part that makes it easy to turn stored data into real objects. Unfortunately, it violates the Open-Close Principle making it difficult to reach your end goal, extendability.
For example, in your code above, your factory function can parse "type1", "type2" and "type3" from your data file and generate objects of type1, type2 and type3 but adding more types would mean editing this function and adding a new else if for every new type you wish to add
You've already identified this as a problem and are trying to solve it using variadic templates. Unfortunately, if you extend the number of game objects into the twenties, thirties, or even hundreds of types, variadic templates will become cumbersome to use, if at all they are able to go that far.
A much simpler solution is to use the Abstract Factory pattern. This essentially shifts responsibility for creating game objects from your file parser's Factory Function, to a factory object. Whether this transfer of power goes to a single function, or a fully-fledged class is up to you. You could also templatise this factory to save on coding.
Each of your factories will have to register their existence with the file parser before the parser is called and extending the parser's capabilities will be as simple as creating a new factory and registering it with the parser.
A simple example would be:
class GameObjectAbstractFactory {
public:
string registeredTypes() const{
// cycle through hash table to return the names of registered factories
}
GameObjectFactory* getFactory(string factoryName){
// return the registered factory, or nullptr if not registered
}
void registerFactory(string factoryName, GameObjectFactory*){
// add the factory if it doesn't exist
}
static GameObjectAbstractFactory* instance(){
// access to Singleton instance
}
private:
GameObjectAbstractFactory(); // enforces Singleton pattern
Hash<string, GameObjectFactory*> registeredFactories;
};
// Interface class for generating concrete types, can be templatised, depending on implementation
class GameObjectFactory{
public:
string name() = 0;
GameObject *createObject() = 0;
};
This would alter your parsing function so that it becomes:
fileParseFunction(string filename)
{
//code that opens file called "filename" and handles tokenizing/parsing
GameObjectAbstractFactory *abstractFactory = GameObjectAbstractFactory::instance();
GameObjectFactory *factory = abstractFactory.getFactory(token);
if(factory != nullptr)
{
gameWorld.add(factory.createObject());
}
//other code to finish loading the level
}
This would then make your fileParseFunction() compliant with the Open-Close Principle in that it could still generate new game objects as your engine is extended but the function itself will not have to be modified in order to do so.
There is a caveat with this pattern though: all the factories need to be registered with the abstract factory before they are needed, otherwise the required game object will not be able to be created.
As I mentioned in the beginning, this answer does not address your direct question about variadic templates but I hope this helps with the extendability of your game engine.

Why isn't my boost::multi_index modify() compiling?

I'm using boost::multi_index_container and am trying to get a modify operation working. My modification routine looks like this (roughly), using a function inner class:
void FooContainer::modifyAttribute(string key, int newValue) {
struct ModifyFunc {
int val;
ModifyFunc(int val): val(val) {}
void operator()(Foo &f) {
foo.val = val;
}
};
StorageContainer::index<keyTag>::type &idx = mContainer.get<keyTag>();
StorageContainer::index<keyTag>::type::iterator iter = idx.find(key);
idx.modify(iter, ModifyFunc(newValue));
}
When I try to compile this, I get a multi-page spew of compiler error like this (most of it omitted):
FooContainer.cpp:##: error: no matching function for call to [...]::modify([...]&, FooContainer::modifyAttribute(string,int)::ModifyFunc)’
What's wrong with this invocation and how can I make it work?
The problem is that function inner classes aren't recognized by the compiler as a valid typename for template parameters; it isn't obvious, but the multi_index_container::index<T>::type::modify method uses the type of the modify parameter as a template argument which is a detail normally hidden from view. However, look at its declaration in, for example, boost/multi_index/hashed_index.hpp:
template<typename Modifier>
bool modify(iterator position,Modifier mod)
The easy fix is to make the ModifyFunc struct not a function inner class; trivially, make it inner to FooContainer rather than to the FooContainer::modifyAttribute method. Of course, this also means that you can reuse the ModifyFunc class elsewhere, if it turns out you need it in more than one place.

Exposing a type-safe dynamic API with a shared library

I'm programming a plugin API interface for an application. The plugins are loaded as shared libraries at run time. They have access to the application API through an interface, such as the following:
class IPluginAPI
{
public:
virtual bool IsPluginsLoaded(void) = 0;
virtual bool IsHookingEnabled(void) = 0;
// And about 50 more methods
};
Plugins can request to 'listen' on certain events (such as MouseClick, MouseScroll etc.). These functions make up a total of >300 different events. Normally I would have done something like this:
extern "C" void SetEventHooks(APITable& table)
{
table.MouseClick = &PluginMouseClickEvent;
table.MouseMove = &PluginMouseMoveEvent;
}
Whereas the SetEventHooksfunction resides within the plugin library and is called from the application, and the plugins can listen to functions of interest by pointing to their functions. This is not the method I want to use, but I want to offer some kind of abstraction instead. This is what I had in mind:
// Interface IPluginAPI supplies a 'SetEventHook` method such as
void SetEventHook(HookID id, void * callback);
In this case HookID is a strong typed enum which contains all function IDs:
enum class HookID
{
MouseClick,
MouseMove,
// ...
};
So the plugin would use this function to listen to events:
pluginAPI->SetEventHook(ID::MouseClick, &myCallback);
The problem with this approach is that it is not type-safe and I cannot use templates directly (since this is done at runtime as libraries). I don't want to expose 300 different functions either for each event (e.gSetHookMouseMove(void (*)(int, int)) and so on). My last idea, is that the plugins have a utility template function which makes this type safe, but I'm not sure how to implement this in a simple way (and without boilerplate code):
template <typename T>
SetEventHook(HookID id, T callback)
{
if(typeof(T) == decltype(/* function type of the ID */))
gPluginAPI->SetEventHook(id, callback);
else static_assert("INVALID FUNCTION TYPE");
}
So to put it simple; how can I enable my plugins to hook to certain events in a dynamic type-safe way without exposing a complete function table and/or >300 methods for each event?
NOTE: I used function pointers for simplification, but I want to use std::function
As suggested by Kerrek, you can use traits policy to solve your problem. Basically as a part of public API you have to include structures defining callback type for each of your hook id.
// The default traits. If you don't want to have default traits comment body
// of this type out (including curly braces).
template <HookID id>
struct CallbackTraits
{
typedef void (*CallbackType)();
};
// Traits for MouseClick
template <>
struct CallbackTraits<HookID::MouseClick>
{
typedef void (*CallbackType)(int);
};
// Traits for MouseDoubleClick are the same
template <>
struct CallbackTraits<HookID::MouseDoubleClick> : CallbackTraits<HookID::MouseClick> {};
// Traits for MouseMove
template <>
struct CallbackTraits<HookID::MouseMove>
{
typedef void (*CallbackType)(int, int);
};
// actual hooking function
template <HookID id>
void SetEventHook(typename CallbackTraits<id>::CallbackType callback)
{
// do something with id and the callback
}
Now you can use this API following way:
// handlers prototypes
void MouseClicked(int button);
void MouseMoved(int x, int y);
void SomeEvent();
int main()
{
// compiles ok
SetEventHook<HookID::MouseClick>(MouseClicked);
SetEventHook<HookID::MouseMove>(MouseMoved);
// won't compile - function signature incompatible
SetEventHook<HookID::MouseDoubleClick>(MouseMoved);
// will compile if you left default traits body uncommented
SetEventHook<HookID::HookWithNoTraitsDefined>(SomeEvent);
return 0;
}
I've uploaded a working sample here.

Automatically Instantiating over a bunch of types in C++

In our library we have a number of "plugins", which are implemented in their own cpp files. Each plugin defines a template function, and should instantiate this function over a whole bunch of types. The number of types can be quite large, 30-100 of them, and can change depending on some compile time options. Each instance really have to be compiled and optimized individually, the performance improves by 10-100 times. The question is what is the best way to instantiate all of these functions.
Each plugin is written by a scientist who does not really know C++, so the code inside each plugin must be hidden inside macros or some simple construct. I have a half-baked solution based on a "database" of instances:
template<int plugin_id, class T>
struct S
{
typedef T (*ftype)(T);
ftype fp;
};
// By default we don't have any instances
template<int plugin_id, class T> S::ftype S::fp = 0;
Now a user that wants to use a plugin can check the value of
S<SOME_PLUGIN,double>::fp
to see if there is a version of this plugin for the double type. The template instantiation of fp will generate a weak reference, so the linker will use the "real" instance if we define it in a plugin implementation file. Inside the implementation of SOME_PLUGIN we will have an instantiation
template<> S<SOME_PLUGIN,double>::ftype S<SOME_PLUGIN,double>::fp =
some_plugin_implementation;
This seems to work. The question is if there is some way to automatically repeat this last statement for all types of interest. The types can be stored in a template class or generated by a template loop. I would prefer something that can be hidden by a macro. Of course this can be solved by an external code generator, but it's hard to do this portably and it interfers with the build systems of the people that use the library. Putting all the plugins in header files solves the problem, but makes the compiler explode (needing many gigabytes of memory and a very long compilation time).
I've used http://www.boost.org/doc/libs/1_44_0/libs/preprocessor/doc/index.html for such magic, in particular SEQ_FOR_EACH.
You could use a type list from Boost.MPL and then create a class template that recursively eats that list and instantiates every type. This would however make them all nested structs of that class template.
Hmm, I don't think I understand your problem correctly, so apologies if this answer is way off the mark, but could you not have a static member of S, which has a static instance of ftype, and return a reference to that, this way, you don't need to explicitly have an instance defined in your implementation files... i.e.
template<int plugin_id, class T>
struct S
{
typedef T (*ftype)(T);
static ftype& instance()
{
static ftype _fp = T::create();
return _fp;
}
};
and instead of accessing S<SOME_PLUGIN,double>::fp, you'd do S<SOME_PLUGIN,double>::instance(). To instantiate, at some point you have to call S<>::instance(). Do you need this to happen automagically as well?
EDIT: just noticed that you have a copy constructor, for ftype, changed the above code.. now you have to define a factory method in T called create() to really create the instance.
EDIT: Okay, I can't think of a clean way of doing this automatically, i.e. I don't believe there is a way to (at compile time) build a list of types, and then instantiate. However you could do it using a mix... Hopefully the example below will give you some ideas...
#include <iostream>
#include <typeinfo>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/algorithm.hpp>
using namespace std;
// This simply calls the static instantiate function
struct instantiate
{
template <typename T>
void operator()(T const& x) const
{
T::instance();
}
};
// Shared header, presumably all plugin developers will use this header?
template<int plugin_id, class T>
struct S
{
typedef T (*ftype)(T);
static ftype& instance()
{
cout << "S: " << typeid(S<plugin_id, T>).name() << endl;
static ftype _fp; // = T::create();
return _fp;
}
};
// This is an additional struct, each plugin developer will have to implement
// one of these...
template <int plugin_id>
struct S_Types
{
// All they have to do is add the types that they will support to this vector
static void instance()
{
boost::fusion::vector<
S<plugin_id, double>,
S<plugin_id, int>,
S<plugin_id, char>
> supported_types;
boost::fusion::for_each(supported_types, instantiate());
}
};
// This is a global register, so once a plugin has been developed,
// add it to this list.
struct S_Register
{
S_Register()
{
// Add each plugin here, you'll only have to do this when a new plugin
// is created, unfortunately you have to do it manually, can't
// think of a way of adding a type at compile time...
boost::fusion::vector<
S_Types<0>,
S_Types<1>,
S_Types<2>
> plugins;
boost::fusion::for_each(plugins, instantiate());
}
};
int main(void)
{
// single instance of the register, defining this here, effectively
// triggers calls to instanc() of all the plugins and supported types...
S_Register reg;
return 0;
}
Basically uses a fusion vector to define all the possible instances that could exist. It will take a little bit of work from you and the developers, as I've outlined in the code... hopefully it'll give you an idea...