I am working on a factory that can register and create classes with a different set a parameter types and numbers. I search over the internet and I managed to create this class:
template< typename Key, typename BaseClass >
class Factory {
static_assert( std::has_virtual_destructor< BaseClass >::value,
"BaseClass must have a virtual destructor" );
public:
template< typename DerivedClass, typename ... Args >
void register_creator( const Key& key )
{
static_assert( std::is_base_of< BaseClass, DerivedClass >::value,
"DerivedClass must be a subclass of BaseClass" );
static_assert( std::is_constructible< DerivedClass, Args... >::value,
"DerivedClass must be constructible with Args..." );
creators_.emplace(
CreatorKey { key, create_function_type_index< Args... >() },
reinterpret_cast< CreateFunc< > >( create_function_impl<
DerivedClass, Args... > ) );
}
template< typename ... Args >
std::unique_ptr< BaseClass > create(
const Key& key,
Args&&... args ) const
{
auto creator = creators_.find(
{ key, create_function_type_index< Args... >() } );
if( creator != creators_.end() ) {
return reinterpret_cast< CreateFunc< Args... > >( creator->second )(
std::forward< Args>( args )... );
} else {
return {};
}
}
private:
template< typename ... Args >
static std::type_index create_function_type_index()
{
return {typeid( CreateFunc<Args...> )};
}
template< typename DerivedClass, typename ... Args >
static std::unique_ptr< BaseClass > create_function_impl(
const Args&... args )
{
return std::unique_ptr< BaseClass > { new DerivedClass {
std::forward< const Args& >( args )... } };
}
template< typename ... Args >
using CreateFunc = typename std::add_pointer< std::unique_ptr< BaseClass >( const Args&... ) >::type;
using CreatorKey = std::pair< Key, std::type_index >;
std::map< CreatorKey, CreateFunc< > > creators_;
};
My goal is to be able to run this kind of code:
class ___A___ {};
class ___B___ {};
class ___Base___ {
public:
virtual ~___Base___() = default;
protected:
___Base___( ___A___ a, ___B___ b ) : a_( a ), b_( b ) {
}
protected:
___A___ a_;
___B___ b_;
};
class ___Derived___: public ___Base___ {
public:
___Derived___( ___A___& a, ___B___& b ) : ___Base___( a, b ) {
}
};
class ___Derived2___: public ___Base___ {
public:
___Derived2___( ___A___ a, ___B___ b ) : ___Base___( a, b ) {
}
};
class ___Derived3___: public ___Base___ {
public:
___Derived3___( ___A___& a, ___B___ b ) : ___Base___( a, b ) {
}
};
Factory< std::string, ___Base___ > factory;
factory.register_creator< ___Derived___, ___A___ &, ___B___& >( "Derived" );
factory.register_creator< ___Derived2___, ___A___, ___B___ >( "Derived2" );
factory.register_creator< ___Derived3___, ___A___ &, ___B___ >( "Derived3" );
___A___ a;
___B___ b;
auto D = factory.create( "Derived", a, b );
auto D2 = factory.create( "Derived2", ___A___(), ___B___() );
auto D3 = factory.create( "Derived3", a, ___B___() );
The registers works perfectly for both reference and value parameters but I cannot manage to instiate them using the creators. During my debugging, I saw that all the parameters where given by reference and never by value.
Aucun commentaire:
Enregistrer un commentaire