Correct usage of ellipsis and template parameters - c++

Turns out I need to build a function that takes a variable number of arguments of no predetermined types,something like:
myFun(int param1, char param2, short param3....);
And I thought about using variadic template functions.
This is actually a member function of a class which is inside a namespace, this is my header file:
//USART.hh file
namespace usartNameSpace
{
class USART
{
public:
USART();
~USART();
template <typename firstArgument, typename ...Arguments> bool parseUserCommands(firstArgument &argument, Arguments &... args);
};
}
This is the implementation(I have omitted both the constructor and destructor)
//USART.cpp file
using namespace usartNameSpace;
template <typename firstArgument, typename ...Arguments> bool USART::parseUsercommands(firstArgument &argument, Arguments&... args)
{
//stuff the function does
}
I will say it again, my goal is to be able to create a method that takes a variable number of parameters of no particular type, with this conception I think I'm able to reach that, however, when calling the method from the main.cpp file, I get the following error at compile time:
undefined reference to `bool usartNameSpace::USART::parseUserCommands<int, char>(int&, char&)'
collect2: error: ld returned 1 exit status
make: *** [makefile:68: mainProject.elf] Error 1
I do not really know what is wrong with my conception of things here, someone told me to try to put the implementation in the same header where the definition lies but that did not work neither(If someone could explain this one also, it would be very nice).
Lastly, here is my main file:
#include "USART.hh"
usartNameSpace::USART coms(USART2);
int n = 8;
char m = 'a';
int main(void)
{
coms.parseUserCommands<int, char>(n, m);
return 0;
}

Template Definition vs Declaration TL;DR
Put the definition of template functions, classes and methods (if isolated to a single class method) in the header file. Anything else can be defined in a source file.
Longer
The problem is that is not possible to have templates definitions (classes, functions and methods) in source files as the compiler need to know the instantiated type when it compiles the file, it can't leave it as a template parameter. In this case you have to put the definition of the template method with its declaration in the header. However, this doesn't mean you have to put non-template method's definitions in the same header, you can even create methods with the same name but aren't templated and split the declaration and definition (as far as my brief testing went).
Variadic Template Use
The pattern you appear to be using is a recursive template parameter function (method in this case but works for both). The key is that this is a recursive pattern thus you need a base method that just takes one (in this case template) argument. The recursive function takes a template initial argument and a second variadic parameter pack. You do what you want with the first argument, then call the method again parsing the variadic arguments (args... with the ellipsis). This will unfold the pack until you it the base class.
Another method would be to take a tuple of variadic arguments and manipulate the tuple so you can access all of the elements in a single function call, removing the need for a recursive variadic call pattern.
You could also (I believe) use std::make_tuple on the variadic pack to make it into a std::tuple and in that case you wouldn't need recursive pattern or the firstArgument parameter, just a function that take Args... args but I didn't explore that in testing. Some homework for you.
Code
Note: This is the code that was tested (briefly). I didn't explore in depth the solution with tuples but provided resources below that will hopefully guide you.
/// USART.hh
/// \note added header guards for completeness
#ifndef USART_H ///< header guard
#define USART_H
#include <iostream>
#include <string>
namespace usartNameSpace
{
class USART
{
public:
USART();
~USART();
/// Base case for recursive call
template<typename FirstA>
bool parseUserCommands(FirstA first)
{
std::cout << first << std::endl;
return true;
}
/// Variadic Resursive call
template<typename FirstA, typename... Args>
bool parseUserCommands(FirstA first, Args... args)
{
std::cout << first << std::endl;
return parseUserCommands(args...);
}
/// Non-template method with the same name as a templated method
bool parseUserCommands();
/// Non template method
void printer(std::string str);
};
}
#endif // USART_H
/// USART.cpp
#include <USART.hh>
namespace usartNameSpace
{
/// Implement all non-template methods in source file (*.cpp)
USART::USART()
{ std::cout << "USART constructor" << std::endl; }
USART::~USART()
{ std::cout << "USART destructor" << std::endl; }
bool USART::parseUserCommands()
{
std::cout << "No arguments" << std::endl;
return true;
}
void USART::printer(std::string str)
{ std::cout << str << std::endl; }
}
/// main.main.cpp
#include <USART.hh>
#include <iostream>
auto main() -> int
{
auto n = 8;
auto c = 'a';
auto s = "Hello";
auto b = true;
usartNameSpace::USART usart;
usart.parseUserCommands(n, c); ///< Two arguments
usart.parseUserCommands(s); ///< One argument
usart.parseUserCommands(n, c, s, b); ///< Four arguments
usart.printer("Bye!"); ///< Non-template method
usart.parseUserCommands(); ///< Non-template method of same name as templated one
return 0;
}
# Output
# Build and run instructions included for completeness
# I can provide a manual build command if requested.
$ bpt build -t :c++20:gcc-11 -o build
$ ./build/main
USART constructor
8
a
Hello
8
a
Hello
1
Bye!
No arguments
USART destructor
Compilers and Tools
GCC-11.3.0
bpt build system
Links and Resources Used
Variadic member function of template class : SO
Why can templates only be implemented in the header file? : SO
Pretty-print std::tuple : SO
For exploring manipulation parameter packs , tuples and variadic fold expressions
Parameter pack : cppreference
std::tuple : cppreference
std::make_tuple : cppreference

Related

Does this method already have a name?

I have found that sometimes functions have very many parameters. A great many of these parameters will be optional and sometimes a group of these options often come from a single other object (so you end up doing foo(Object.GetN(), Object.GetM(), Object.GetK())). A common way to deal with it is to create different overloads for different situations that it might be called:
foo(int n, int m, int k /*, and on and on*/);
foo(bool b, int m/*, ...*/);
foo(int m, int k/*, ...*/);
foo(Object_t object/*, ...*/);
//...
The problem here is that which parameter is which isn't particularly intuitive and you can get quite the surprise when you call a different overload than what you intended.
Recently I had an idea to make it easier to get the function call right and make life easier for myself when dealing with these functions that have many different ways of being called. This solution doesn't cover every possible necessity out there, but it works quite well for me.
Instead of creating different overloads for everything, I would create 1 function that simply takes a variadic number of parameters and then extract possible parameters for use inside the function. As for the parameters, I would wrap them in helper classes that would be created for these functions. This would allow for the user declaring what each integer or boolean or string or what-have-you means instead of relying on positional information within the function's signature.
Instead of foo(n, m) (which going by the names of the variables above suggests a likely bug) you would call foo(OptN(n), OptM(m)) making it completely clear what each parameter is going to be used for and much harder to have a parameter be misinterpreted.
I will include a MCVE at the end if anyone's interested in 1 possible implementation of this.
I have never seen or heard of this technique before, but I also have a hard time believing that I'm the first one to think of it. So, finally, my question is simply does this technique have a name already?
If it doesn't have a name already, I have been calling these functions 'declarative functions' since you declare what each parameter represents explicitly instead of 'positional functions' relying on where the parameter appears to give it its meaning.
MCVE:
#include <iostream>
#include <utility>
struct Option1
{
Option1(bool b):b(b){}
bool b;
bool operator()() const {return b;}
};
struct Option2
{
Option2(int n):n(n){}
int n;
int operator()() const {return n;}
};
struct Group : Option1, Option2
{
Group(bool b, int n):Option1(b), Option2(n){}
};
/*
* Get the option from what the user gave us.
*/
template <class OptionType, class OptionsGetter, class RType>
auto GetOptionImpl(const OptionsGetter & options_getter,
const RType&, std::true_type) ->
decltype(((const OptionType&)options_getter)())
{
return ((const OptionType&)options_getter)();
}
/*
* Get the default value specified since the user didn't pass
* in that option
*/
template <class OptionType, class OptionsGetter, class RType>
RType GetOptionImpl(const OptionsGetter&, const RType & d, std::false_type)
{
return d;
}
/**
* Returns the value of the option OptionType if the user
* passed that in (inside OptionsGetter) and returns the
* default value if they didn't pass it in.
*/
template <class OptionType, class OptionsGetter, class RType>
auto GetOption(const OptionsGetter & oOptionsGetter,
const RType & oDefault) ->
decltype(std::declval<OptionType>()())
{
return GetOptionImpl<OptionType>(oOptionsGetter, oDefault,
std::is_base_of<OptionType, OptionsGetter>());
}
template <class ... Params>
void foo(Params ... params)
{
struct ParamsGetter : Params...
{
ParamsGetter(Params ... p): Params(p)...{}
} params_getter(params...);
if(GetOption<Option1>(params_getter, false))
std::cout << "Option 1 was true ";
else
std::cout << "Option 1 was false ";
std::cout << "Option 2: " << GetOption<Option2>(params_getter, 3) << '\n';
}
int main()
{
foo(Option1{true}, Option2{22});
foo();
foo(Option2{1});
foo(Group(true, 2));
}
Output:
Option 1 was true Option 2: 22
Option 1 was false Option 2: 3
Option 1 was false Option 2: 1
Option 1 was true Option 2: 2
As mentioned in a comment, this concept is called named parameter. See the explanation on wikipedia, as well as for instance this proposal to introduce it in C++.
I think this is commonly called an opaque typedef or a strong typedef. The idea is to solve the exact problem you're describing - you have types that have integral values but you want to make it possible to explicitly set them.
For more motivation on this concept, you can see this proposal for inclusion in the language and Boost's implementation of it.

Can I use template parameter as argument to non-template method?

I am looking to move some of the code of within a template method to a non-template method in order to decrease the binary size.
There is a template class called 'Target', as illustrated below
template<TargetType K, typename V = plat_target_handle_t>
class Target
{
.............
..............
};
TargetType is an enum data type.
template<>
template< TargetType T>
std::vector<Target<T> >
Target<TARGET_TYPE_X>::getChildren(const TargetState i_state) const
{
std::vector<Target<T> > l_children;
for ( int i=0; i < elements_in_some_list ; ++i)
{
/*If the current entry in some_list match my critera, add to the l_children */
}
}
TargetType is an enum data type and TARGET_TYPE_X is one of the enum values.
I want to move all the logic to select the children to a global method, lets say getChildrenHelper.
getChildrenHelper is declared as below.
void getGhildrenHelper(const TargetType i_targetType,
const TargetState i_targetstate,
std::vector<Target<TARGET_TYPE_ALL>> & io_children);
And then the getChildren method would eventually look like
template<>
template< TargetType T>
std::vector<Target<T> >
Target<TARGET_TYPE_X>::getChildren(const TargetState i_state) const
{
std::vector<Target<T> > l_children;
childHelper(T,i_state,l_children);
return l_children;
}
My guess is this cannot be done, though the native compiler that I am working with did not through an error.
However there is another existing code where the similar concept is working perfectly fine
template< TargetType K >
inline ReturnCode putParam(const Target<K>& i_target,
const RingID i_ringID,
const RingMode i_ringMode)
{
ReturnCode l_rc = FAPI2_RC_SUCCESS;
// Find the string in the SEEPROM
l_rc = findInImageAndApply(i_target, i_ringID, i_ringMode);
return l_rc;
}
fapi2::ReturnCode findImageAndApply(
const fapi2::Target<fapi2::TARGET_TYPE_ALL>& i_target,
const RingID i_ringID,
const fapi2::RingMode i_ringMode)
{
................
................
}
It is quite common for template functions to invoke ordinary, non-template functions in order to execute a large chunk of code that does not need or use any template parameters. This is a common technique for avoiding template-generated code bloat.
In your case, TargetType appears is a template parameter, and there is no such class. As such:
void getGhildrenHelper(const TargetType i_targetType,
const TargetState i_targetstate,
std::vector<Target<TARGET_TYPE_ALL>> & io_children);
that by itself should not compile, since TargetType appears to be a template parameter, and not a class name, based on the code in your template specialization.
But, your code might be ambiguous, here. In any case, if neither TargetType and TargetState, nor Target<TARGET_TYPE_ALL> are template parameters, this would make this an ordinary function, and it can certainly be invoked from a template function, with matching parameters.
A template function can do anything that an ordinary function does, including calling other functions, or using other templates. The requirements are the same as for any other function: matching function parameter types, etc...

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.

GCC Segfaults When `decltype` Used in Nested Lambda

I created a macro that conveniently builds lambda functions using which I can iterate through tensor objects in a library that I wrote. However, nesting these macros seemed to cause GCC to undergo an internal segmentation fault. Upon expanding the compiler's preprocessor output and going through some trial and error, I discovered that cause seems to be the use of decltype in the parameter list of a nested lambda function declared in the method of a class or struct. Below follows a minimal example using the standard library.
#include <iostream>
#include <type_traits>
template <class Iterator, class Func>
void for_each(const Iterator first, const Iterator last, Func func)
{
for (Iterator it = first; it != last; ++it) {
func(*it);
}
}
template <class T>
class helper
{
typedef typename T::size_type type;
};
template <class T>
class helper<T&>
{
typedef typename T::size_type type;
};
template <class T>
class helper<T*>
{
typedef typename T::size_type type;
};
struct bar
{
struct foo
{
typedef int size_type;
} foo_;
void test()
{
int arr[] = { 1, 2, 3 };
for_each(arr, arr + 3, [&](int i) {
/*
** XXX: The "typename ... type" segfaults g++!
*/
for_each(arr, arr + 3, [&](typename helper<decltype(foo_)>::type j) {
});
});
}
};
int main()
{
return 0;
}
Compiler Output:
$ g++ -Wall -std=c++0x nested_lambda.cpp
nested_lambda.cpp: In lambda function:
nested_lambda.cpp:42:56: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-4.6/README.Bugs> for instructions.
Preprocessed source stored into /tmp/ccqYohFA.out file, please attach this to your bugreport.
I initially opted to use decltype because an object is passed to a macro, and I need to extract the object's type. From the object's type, (T, T&, or T*), I'd use a traits class to pull T::size_type. size_type would then be the type of the lambda function parameters.
How can I circumvent this issue without having to use a typedef to declare the type of the lambda function parameter in advance? If you can think of some other solution that could easily be implemented in a macro (i.e. copied and pasted repeatedly in the parameter list of a lambda function), that would work too.
As a very rough workaround for those who may be experiencing similar issues, the best standard solution I could come up with involved having the macro declare a typedef in advance, concatenating GUID-like prefix (I personally recommend _qki_zbeu26_w92b27bqy_r62zf91j2n_s0a02_) and __LINE__ to generate some warbled nonsense for the typedef name. With all luck, this name will not clash with any other definitions.
To ensure that the same __LINE__ gets concatenated even when the warbled name is used for the lambda function parameter types, the warbled name will need to be generated by a macro that is initially passed a macro parameter, as in the code sample below.
#define _foo_GUID \
_qki_zbeu26_w92b27bqy_r62zf91j2n_s0a02_
#define _foo_MANGLE_IMPL2(a, b) \
a ## b
#define _foo_MANGLE_IMPL(a, b) \
_foo_MANGLE_IMPL2(a, b)
#define _foo_MANGLE(a) \
_foo_MANGLE_IMPL(_foo_GUID, a)
When passing _foo_MANGLE(__LINE__) as a macro parameter, please ensure that there is an extra level of indirection so that _foo_MANGLE(__LINE__) gets evaluated before it is used.
This bug is currently being addressed, and I think that it should be fixed soon.

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...