Re: Preprocessor magic to expand template instantiation ?
* Juha Nieminen:
Alf P. Steinbach wrote:
I fail to understand why the OP, and now you, cannot see the trivial
solution, which is to use a map of functions, or just a simple array.
It's on a par with using a variable where you need a variable. And
actually it is exactly that, using a variable where you need one, that's
the level of the question.
How do you populate the map without basically replicating his Create()
function?
There are a number of possibilites.
If the type numbers are consecutive then a recursive template can do it.
If the type numbers are more arbitrary then with each specialization of the
Factory<N> type include registration in the map.
If the map isn't used before entry of 'main', then each of the OP's Factory<N>
types can be self-registrating, like this (eror handing omited):
<code>
#include <map>
struct Type { virtual ~Type() {} };
struct Type1: Type {};
struct Type2: Type {};
typedef Type* (*FactoryFunc)();
typedef std::map<int, FactoryFunc> FactoryFuncs;
FactoryFuncs& factoryFuncs()
{
static FactoryFuncs theFuncs;
return theFuncs;
}
template< int N, class T >
struct RegisterFactoryFunc
{
static Type* create() { return new T(); }
static bool registerFactory()
{
factoryFuncs()[N] = &create;
return true;
}
static bool const theRegistrar;
};
template< int N, class T >
bool const RegisterFactoryFunc<N, T>::theRegistrar =
RegisterFactoryFunc<N, T>::registerFactory();
enum TypeNumber
{
typeNumber1,
typeNumber2
};
template struct RegisterFactoryFunc< typeNumber1, Type1 >;
template struct RegisterFactoryFunc< typeNumber2, Type2 >;
Type* create( TypeNumber n )
{
return factoryFuncs()[n]();
}
#include <iostream>
#include <typeinfo>
int main()
{
using namespace std;
Type* const p1 = create( typeNumber1 );
Type* const p2 = create( typeNumber2 );
cout << typeid(*p1).name() << endl;
cout << typeid(*p2).name() << endl;
}
</code>
Cheers & hth.,
- Alf