Наследование и хранение статической информации о классе - PullRequest
0 голосов
/ 23 июня 2010

Я пытаюсь настроить некоторые вещи с помощью Lua, но особенности Lua не важны для моего вопроса.

То, что я хотел бы сделать, это вызвать функцию, скажем OpenLib<T>(L), и заставить ее получить имя таблицы для определенного класса (а также его таблицы) и зарегистрировать его в Lua.По сути это сводится к следующему:

template <class T>
static void OpenLib(lua_State* L)
{
    // this func does some other stuff too that I'm omitting, important bit below
    if (T::myTable && T::myTableName)
    {
        luaL_openlib(L, T::myTableName, T::myTable, 0);
    }
}

Я пробовал это несколькими разными способами, и я не могу заставить его работать правильно.Я попытался создать базовый класс, содержащий myTable и myTableName, например:

class LuaInfo
{
public:
    static const char* myTableName;
    static luaL_reg* myTable;
}

Тогда я мог бы просто наследовать от LuaInfo, а затем заполнить необходимую информацию.Это не сработало, потому что все классы, наследуемые от LuaInfo, получали бы одну и ту же информацию, поэтому я огляделся по сторонам, и у меня возникла идея сделать это:Теперь я должен сделать класс Widget: public LuaInfo, но это было ближе к работе.

template <class T>
void OpenLib(lua_State* L)
{
    if (T::myTable && T::myTableName)
    {
        luaL_openlib(L, LuaInfo<T>::myTableName, LuaInfo<T>::myTable, 0);
    }
}

Я попробовал несколько вариантов этого, чтобы попытаться понять это правильно, но я продолжаю получать ошибки, такие как

undefined reference to `ag::LuaInfo<ag::ui::Widget>::myTable'

Возможно ли то, что я хочу сделать, и если да, то, как правильно это делать?

Ответы [ 2 ]

1 голос
/ 23 июня 2010

Использование

template<typename T>
class LuaInfo
{
  static const char* myTableName;
  static lua_reg* myTable;
};

должно работать нормально.

Ваша проблема в том, что вам нужно определить статические переменные.

Один исходный файл, содержащий несколько строк, как это, решит его

luaL_reg* LuaInfo<ag::ui::Widget>::myTable = 0;
const char * LuaInfo<ag::ui::Widget>::myTableName = 0;

luaL_reg* LuaInfo<ag::ui::OtherClass>::myTable = 0;
const char * LuaInfo<ag::ui::OtherClass>::myTableName = 0;

и т. Д.

Возможно, вы захотите определить макрос, чтобы сделать это лучше.

#define LUAINFOIMPL(X) luaL_reg* LuaInfo<X>::myTable=0; const char * LuaInfo<X>::myTableName=0
LUAINFOIMPL( ag::ui::Widget );
LUAINFOIMPL( ag::ui::OtherClass );

Однако немного уродливо так масштабировать. Я думал, что шаблоны стилей черт могут решить эту проблему ... но я не уверен, что они масштабируются лучше.

0 голосов
/ 23 июня 2010

Ваша первая попытка отлично работает для меня.Я полагаю, вы просто забыли инициализировать статические члены и получили некоторые ошибки ссылки по этому поводу.Вот что я сделал:

template <class T>
static void OpenLib(lua_State* L)
{
    // this func does some other stuff too that I'm omitting, important bit below
    if (T::myTable && T::myTableName)
    {
        luaL_openlib(L, T::myTableName, T::myTable, 0);
    }
}

class LuaInfo
{
    public:
        static const char* myTableName;
        static luaL_reg* myTable;
};

//init static members
const char*  LuaInfo::myTableName = 0;
luaL_reg* LuaInfo::myTable = 0;

int main()
{
    OpenLib<LuaInfo>(0);
}

Теперь, если вы хотите дать другую информацию OpenLib, вам нужно создать новый класс, такой как LuaInfo, и дать этот новый класс в качестве параметров шаблона.

Но почему вы хотите эту информацию в качестве параметров шаблона?ИМО, это намного проще:

struct LuaInfo
{
    const char* myTableName;
    luaL_reg* myTable;
};

static void OpenLib(lua_State* L, LuaInfo info)
{
    // this func does some other stuff too that I'm omitting, important bit below
    if (info.myTable && info.myTableName)
    {
        luaL_openlib(L, info.myTableName, info.myTable, 0);
    }
}

int main()
{
    LuaInfo info = {/*some values here*/};
    OpenLib(0, info);
}
...