I have the following templated function...
template< class T > T *create_object( lua_State *L )
{
// Get a raw block of memory, managed by Lua.
void *mem = lua_newuserdata( L, sizeof( T ) );
// Construct the object in the allocated memory.
T *object = new (mem) T;
// Do other stuff here...
return object;
}
... that allocates and sets up a C++ object for use in the Lua scripting language. I'd like to extend this function so I can pass in arguments for the object's constructor. It might look something like this:
template< class T > T *create_object( lua_State *L, ??? ctor_args )
{
void *mem = lua_newuserdata( L, sizeof( T ) );
T *object = new (mem) T( ctor_args ); // Call correct constructor as determined by args.
// ...
return object;
}
... and work something like this:
class widget
{
public:
// Multiple constructors
widget(); // #1
widget( const widget &w ); // #2
widget( int width, int height, float x, float y ); //#3
};
class font
{
public:
font( std::vector<uint8_t> );
}
// Other classes with multiple constructors.
// Example usage: (L = lua_State pointer)
create_object<widget>( L ); // Pass no arguments - use constructor #1
create_object<widget>( L, existing_widget ); // Pass one argument- use constructor #2
create_object<widget>( L, 128, 64, 100.0f, 100.0f ); // Pass 4 arguments - use construct #3
create_object<font>( L, buffer ); // Just to show it needs to work with many object types...
... and so on ...
Avoiding a variadic template that ends up like this:
create_object<widget, int, int, float, float >( L, 256, 512, 120.0f, 0.0f );
Would be nice.
Is this possible in c++11?
Update: I'm currently using gcc 4.6 with -pedantic turned on. Non compiler-specific solutions would be preferred.
Like this, provided you have proper support for variadic templates:
template< class T, typename... Args >
T *create_object( lua_State *L, Args&&... args)
{
void *mem = lua_newuserdata( L, sizeof( T ) );
T *object = new (mem) T(std::forward<Args>(args)...);
// ...
return object;
}
This will correctly forward references, even your constructor takes some of its arguments by (const or not) reference and other by value.