A bizarre C++ wart wants us to declare FromStack overloads

before the ThemeMetric templates that use them.  That's broken
and unreasonable, so change this around a bit and make FromStack
(and Push) templates.

Push() takes a bit of a trick.  Some Push overloads push the
actual value: scalars (int, float), RageColor (pushes a table).
Others--most of them--push a reference to a C++ object.  We
want the scalars to have a reference parameter type, so we
don't make extra copies of things like RageColor when we push
them.  We need to pass C++ objects by pointer (we need to
push the actual object's pointer, not a pointer to a copy).
Further, pushing a scalar is a const operation, but pushing
a reference to an object is not.

To do both with the same template, we handle objects with
this slightly odd template:

template<> void LuaHelpers::Push<T*>( lua_State *L, T *const &pObject );

The actual overload (T) is eg. "Actor*"; this fits within the
general prototype, "Push(lua_State *L, const T &object)", giving
us a const reference to a (non-const) pointer to Actor, and we're
conceptually pushing the pointer.

The net effect of this is that 1: what was before compile errors
now becomes link time errors, but 2: these specializations
don't have to be in the headers (except for new ones for
Preference and BroadcastOnChange).
This commit is contained in:
Glenn Maynard
2006-10-07 01:22:28 +00:00
parent 2aa4b1a142
commit 4b30d3552d
11 changed files with 67 additions and 60 deletions
+4 -5
View File
@@ -127,9 +127,8 @@ const RString &EnumToString( int iVal, int iMax, const char **szNameArray, auto_
return (X)(i+1); /*invalid*/ \
}
#define LuaDeclareType(X) \
namespace LuaHelpers { bool FromStack( lua_State *L, X &Object, int iOffset ); } \
namespace LuaHelpers { void Push( lua_State *L, const X &Object ); }
// currently unused
#define LuaDeclareType(X)
#define LuaXType(X) \
template struct EnumTraits<X>; \
@@ -162,8 +161,8 @@ static void Lua##X(lua_State* L) \
REGISTER_WITH_LUA_FUNCTION( Lua##X ); \
template<> X EnumTraits<X>::Invalid = enum_add2( NUM_##X, 1 ); \
template<> const char *EnumTraits<X>::szName = #X; \
bool LuaHelpers::FromStack( lua_State *L, X &Object, int iOffset ) { Object = Enum::Check<X>( L, iOffset ); return true; } \
void LuaHelpers::Push( lua_State *L, const X &Object ) { Enum::Push<X>( L, Object ); }
namespace LuaHelpers { template<> bool FromStack<X>( lua_State *L, X &Object, int iOffset ) { Object = Enum::Check<X>( L, iOffset ); return true; } } \
namespace LuaHelpers { template<> void Push<X>( lua_State *L, const X &Object ) { Enum::Push<X>( L, Object ); } }
#endif
+1 -1
View File
@@ -156,7 +156,7 @@ public:
void T::PushSelf( lua_State *L ) { Luna<B>::PushObject( L, Luna<T>::m_sClassName, this ); } \
static Luna##T registera##T; \
/* Call PushSelf, so we always call the derived Luna<T>::Push. */ \
namespace LuaHelpers { template<> void Push( lua_State *L, T *pObject ) { pObject->PushSelf( L ); } }
namespace LuaHelpers { template<> void Push<T*>( lua_State *L, T *const &pObject ) { pObject->PushSelf( L ); } }
#define DEFINE_METHOD( method_name, expr ) \
static int method_name( T* p, lua_State *L ) { LuaHelpers::Push( L, p->expr ); return 1; }
+32 -17
View File
@@ -21,6 +21,19 @@ static LuaFunctionList *g_LuaFunctions = NULL;
#pragma warning (disable : 4611)
#endif
namespace LuaHelpers
{
template<> void Push<bool>( lua_State *L, const bool &Object );
template<> void Push<float>( lua_State *L, const float &Object );
template<> void Push<int>( lua_State *L, const int &Object );
template<> void Push<RString>( lua_State *L, const RString &Object );
template<> bool FromStack<bool>( Lua *L, bool &Object, int iOffset );
template<> bool FromStack<float>( Lua *L, float &Object, int iOffset );
template<> bool FromStack<int>( Lua *L, int &Object, int iOffset );
template<> bool FromStack<RString>( Lua *L, RString &Object, int iOffset );
}
struct ChunkReaderString
{
ChunkReaderString( const RString &sBuf ): m_sBuf(sBuf) { m_bDone = false; }
@@ -68,25 +81,27 @@ void LuaManager::UnsetGlobal( const RString &sName )
LUA->Release( L );
}
void LuaHelpers::Push( lua_State *L, const bool &Object ) { lua_pushboolean( L, Object ); }
void LuaHelpers::Push( lua_State *L, const float &Object ) { lua_pushnumber( L, Object ); }
void LuaHelpers::Push( lua_State *L, const int &Object ) { lua_pushinteger( L, Object ); }
void LuaHelpers::Push( lua_State *L, const RString &Object ) { lua_pushlstring( L, Object.data(), Object.size() ); }
bool LuaHelpers::FromStack( Lua *L, bool &Object, int iOffset ) { Object = !!lua_toboolean( L, iOffset ); return true; }
bool LuaHelpers::FromStack( Lua *L, float &Object, int iOffset ) { Object = (float)lua_tonumber( L, iOffset ); return true; }
bool LuaHelpers::FromStack( Lua *L, int &Object, int iOffset ) { Object = lua_tointeger( L, iOffset ); return true; }
bool LuaHelpers::FromStack( Lua *L, RString &Object, int iOffset )
namespace LuaHelpers
{
size_t iLen;
const char *pStr = lua_tolstring( L, iOffset, &iLen );
if( pStr != NULL )
Object.assign( pStr, iLen );
else
Object.clear();
template<> void Push<bool>( lua_State *L, const bool &Object ) { lua_pushboolean( L, Object ); }
template<> void Push<float>( lua_State *L, const float &Object ) { lua_pushnumber( L, Object ); }
template<> void Push<int>( lua_State *L, const int &Object ) { lua_pushinteger( L, Object ); }
template<> void Push<RString>( lua_State *L, const RString &Object ) { lua_pushlstring( L, Object.data(), Object.size() ); }
return pStr != NULL;
template<> bool FromStack<bool>( Lua *L, bool &Object, int iOffset ) { Object = !!lua_toboolean( L, iOffset ); return true; }
template<> bool FromStack<float>( Lua *L, float &Object, int iOffset ) { Object = (float)lua_tonumber( L, iOffset ); return true; }
template<> bool FromStack<int>( Lua *L, int &Object, int iOffset ) { Object = lua_tointeger( L, iOffset ); return true; }
template<> bool FromStack<RString>( Lua *L, RString &Object, int iOffset )
{
size_t iLen;
const char *pStr = lua_tolstring( L, iOffset, &iLen );
if( pStr != NULL )
Object.assign( pStr, iLen );
else
Object.clear();
return pStr != NULL;
}
}
void LuaHelpers::CreateTableFromArrayB( Lua *L, const vector<bool> &aIn )
+3 -10
View File
@@ -81,17 +81,10 @@ namespace LuaHelpers
void PushValueFunc( lua_State *L, int iArgs );
template<class T>
void Push( lua_State *L, T *pObject );
void Push( lua_State *L, const T &Object );
void Push( lua_State *L, const bool &Object );
void Push( lua_State *L, const float &Object );
void Push( lua_State *L, const int &Object );
void Push( lua_State *L, const RString &Object );
bool FromStack( Lua *L, bool &Object, int iOffset );
bool FromStack( Lua *L, float &Object, int iOffset );
bool FromStack( Lua *L, int &Object, int iOffset );
bool FromStack( Lua *L, RString &Object, int iOffset );
template<class T>
bool FromStack( lua_State *L, T &Object, int iOffset );
template<class T>
bool Pop( lua_State *L, T &val )
+14 -11
View File
@@ -163,19 +163,22 @@ RString LuaReference::Serialize() const
return sRet;
}
bool LuaHelpers::FromStack( lua_State *L, LuaReference &Object, int iOffset )
namespace LuaHelpers
{
lua_pushvalue( L, iOffset );
Object.SetFromStack( L );
return true;
}
template<> bool FromStack<LuaReference>( lua_State *L, LuaReference &Object, int iOffset )
{
lua_pushvalue( L, iOffset );
Object.SetFromStack( L );
return true;
}
bool LuaHelpers::FromStack( lua_State *L, apActorCommands &Object, int iOffset )
{
LuaReference *pRef = new LuaReference;
FromStack( L, *pRef, iOffset );
Object = apActorCommands( pRef );
return true;
template<> bool FromStack<apActorCommands>( lua_State *L, apActorCommands &Object, int iOffset )
{
LuaReference *pRef = new LuaReference;
FromStack( L, *pRef, iOffset );
Object = apActorCommands( pRef );
return true;
}
}
LuaTable::LuaTable()
-6
View File
@@ -51,12 +51,6 @@ private:
typedef AutoPtrCopyOnWrite<LuaReference> apActorCommands;
namespace LuaHelpers
{
bool FromStack( lua_State *L, LuaReference &Object, int iOffset );
bool FromStack( lua_State *L, apActorCommands &Object, int iOffset );
}
class LuaTable: public LuaReference
{
public:
+3
View File
@@ -3,6 +3,7 @@
#ifndef MessageManager_H
#define MessageManager_H
#include "LuaManager.h"
struct lua_State;
enum Message
@@ -201,6 +202,8 @@ public:
bool operator != ( const T &other ) const { return val != other; }
};
namespace LuaHelpers { template<class T> void Push( lua_State *L, const BroadcastOnChange<T> &Object ) { LuaHelpers::Push<T>( L, Object.Get() ); } }
template<class T, int N>
class BroadcastOnChange1D
{
+3
View File
@@ -5,6 +5,7 @@
#include "EnumHelper.h"
#include "RageUtil.h"
#include "LuaManager.h"
class XNode;
struct lua_State;
@@ -115,6 +116,8 @@ private:
void (*m_pfnValidate)(T& val);
};
namespace LuaHelpers { template<typename T, typename U> void Push( lua_State *L, const Preference<T, U> &Object ) { LuaHelpers::Push<T>( L, Object.Get() ); } }
template <class T>
class Preference1D
{
+6 -3
View File
@@ -36,10 +36,13 @@ void RageColor::FromStack( lua_State *L, int iPos )
lua_pop( L, 5 );
}
bool LuaHelpers::FromStack( lua_State *L, RageColor &Object, int iOffset )
namespace LuaHelpers
{
Object.FromStack( L, iOffset );
return true;
template<> bool FromStack<RageColor>( lua_State *L, RageColor &Object, int iOffset )
{
Object.FromStack( L, iOffset );
return true;
}
}
static const char *CullModeNames[] =
-5
View File
@@ -200,11 +200,6 @@ public:
float r, g, b, a;
} SM_ALIGN(16);
namespace LuaHelpers
{
bool FromStack( lua_State *L, RageColor &Object, int iOffset );
}
/* Convert floating-point 0..1 value to integer 0..255 value. *
*
* As a test case,
+1 -2
View File
@@ -72,10 +72,9 @@ public:
{
if( m_sName != "" && THEME && THEME->IsThemeLoaded() )
{
using namespace LuaHelpers;
Lua *L = LUA->Get();
THEME->PushMetric( L, m_sGroup, m_sName );
if( !FromStack(L, m_currentValue, -1) )
if( !LuaHelpers::FromStack(L, m_currentValue, -1) )
m_currentValue = T();
lua_pop( L, 1 );
LUA->Release(L);