Russian Qt Forum
Ноябрь 23, 2024, 19:39 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Мини-интепретатор  (Прочитано 7159 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Сентябрь 28, 2011, 19:33 »

Добрый вечер

Ну это даже меньше чем мини Улыбающийся - просто надо подавать данные в OpenGL (GLSL). Чтобы не грузить спецификой, вот псевдокод самой "подачи"
Код
C++ (Qt)
// внутренняя переменная OpenGL с именем name будет установлена в значение val
void SetFloatGL( const char * name, float val );  
 
// для массива int
void SetIntArrayGL( const char * name, const int * src, int count );  
 
и.т.п.
 
Вызывать эти ф-ции непосредственно я не могу - в тот момент когда данные мне известны даже неясно есть ли OpenGL вообще. Поэтому мне надо сохранить данные в каком-то контейнере, а когда дело дойдет до рендера OpenGL - зарядить. Недолго думая, сделал примерно так

Код
C++ (Qt)
struct CVarGL {
CVarGL( int type = type_None ) : mType(type) {}
virtual CVarGL( void ) {}
 
static void SetInt( const char * name, int val );
static void SetFloat( const char * name,  float val );
static void SetIntArray( const char * name,  int * val, size_t count );
 
int mType;
static std::map <const char *, CVarGL *> mMap;
};
 
struct CVarIntGL : public CVarGL {
CVarIntGL( int val ) : CVarGL(type_Int), mData(val) {}
 
int mData;
};
 
// и.т.д (подробности легко понятны)
 
Это работает, но реализация мне не нравится. Получается неприятно много приведений, разборок switch и довольно обильный текст уже на 4-5 типах данных. Нет ли лучшего решения?

Примечания: Qt в проекте нет, поэтому советы типа "смотри в сторону QVariant" бесполезны. Типов данных немного (до 10), для данных типа "массив" нужна возможность очищать и добавлять элементы

Спасибо
Записан
SimpleSunny
Гость
« Ответ #1 : Сентябрь 28, 2011, 20:23 »

Qt в проекте нет, поэтому советы типа "смотри в сторону QVariant" бесполезны.

А почему бесполезны? Почему не посмотреть как это сделано в QVariant (boost::any, boost::variant) и не сделать аналогично.
Записан
BRE
Гость
« Ответ #2 : Сентябрь 29, 2011, 08:40 »

Код
C++ (Qt)
class Var
{
public:
virtual void apply() = 0;
};
 
class VarInt : public Var
{
public:
VarInt( int val );
virtual void apply();
 
private:
int m_val;
};
 
class VarFloat : public Var
{
public:
VarInt( float val );
virtual void apply();
 
private:
float m_val;
};
 
// ------------------------------
// Заполнили команды
std::list<Var*> varList;
 
varList.push_back( new VarInt( 10 ) );
varList.push_back( new VarFloat( 123.45 ) );
...
 
// ------------------------------
// Испольнили команды
foreach( Var *v, varList )
{
v->apply()
}
 
 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Сентябрь 29, 2011, 08:45 »

А почему бесполезны? Почему не посмотреть как это сделано в QVariant (boost::any, boost::variant) и не сделать аналогично.
Это выглядит разумно, но редко получается Улыбающийся Тот же QVariant потянет за собой массу др. хедеров и типов, процесс "подсматривания идеи" оказывается очень долгим. В итоге часто получается что копировать невыгодно, нужна более "легкая" вещь - для использования всего нескольких нужных возможностей.

По существу я спрашиваю простой вещь: как сделать удобный контейнер разнотипных элементов?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Сентябрь 29, 2011, 09:06 »

Код
C++ (Qt)
class Var
{
public:
virtual void apply() = 0;
};
 
У переменной есть имя, поэтому std::map вместо std::list - но не суть. Подход с виртуал не спасает от создания каждого нового типа и утомительных "дешифраций". Сэкономив немного на хранении mType получим более громоздкий dynamic_cast - ну или &typeiid. Думал так
Код
C++ (Qt)
template <class T, size_t type>
struct CVar : public СVarGL {
CVar( void ) { mType = type; }
T mData;
};
 
Но "декодировать" все равно придется  Плачущий
Записан
BRE
Гость
« Ответ #5 : Сентябрь 29, 2011, 09:16 »

Подход с виртуал не спасает от создания каждого нового типа и утомительных "дешифраций".
Понятно что не спасает от создания каждого нового типа. Телепатических компиляторов еще не придумали. Смеющийся
Кстати, можно упростить с помощью шаблонов.

А вот про какие утомительные дешифрации идет речь? Не понятно.

Ладно опишу один тип полней (в дальнейшем легко делается шаблон):
Код
C++ (Qt)
class VarInt : public Var
{
public:
VarInt( const std::string &name, int val ) : m_name( name ), m_val( val ) {}
virtual void apply()
{
SetIntGL( m_name.c_str(), m_val );
}
private:
std::string m_name;
int m_val;
};
 
« Последнее редактирование: Сентябрь 29, 2011, 09:27 от BRE » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Сентябрь 29, 2011, 10:41 »

Ладно опишу один тип полней (в дальнейшем легко делается шаблон):
Код
C++ (Qt)
class VarInt : public Var
{
public:
VarInt( const std::string &name, int val ) : m_name( name ), m_val( val ) {}
virtual void apply()
{
SetIntGL( m_name.c_str(), m_val );
}
private:
std::string m_name;
int m_val;
};
 
Прошу показать как сделать шаблон для такой реализации
Записан
BRE
Гость
« Ответ #7 : Сентябрь 29, 2011, 13:04 »

Код
C++ (Qt)
#include <iostream>
#include <list>
 
void setIntGL( const char *name, int val )
{
       std::cout << "Call setIntGL( " << name << ", " << val << " )"  << std::endl;
}
 
void setFloatGL( const char *name, float val )
{
       std::cout << "Call setFloatGL( " << name << ", " << val << " )"  << std::endl;
}
 
class Var
{
public:
       virtual void    apply() = 0;
};
 
template<typename T, void (*func)( const char *, T )>
class NumVar : public Var
{
public:
       NumVar( const std::string &name, T val ) : m_name( name ), m_val( val ) {}
 
       virtual void    apply() { (*func)( m_name.c_str(), m_val ); }
 
private:
       std::string             m_name;
       T                               m_val;
};
 
int main ( int argc, char *argv[] )
{
       typedef std::list<Var*> VarList;
       VarList varList;
 
       varList.push_back( new NumVar<int, setIntGL>( "Var1", 10 ) );
       varList.push_back( new NumVar<float, setFloatGL>( "Var2", 10.123 ) );
 
       for( VarList::iterator it = varList.begin(); it != varList.end(); ++it )
               (*it)->apply();
 
}
 
« Последнее редактирование: Сентябрь 29, 2011, 13:12 от BRE » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Сентябрь 29, 2011, 13:15 »

Код
C++ (Qt)
template<typename T, void (*func)( const char *, T )>
 
Так было бы хорошо, но ф-ции установки принимают разные аргументы (см первый пост темы)
Записан
BRE
Гость
« Ответ #9 : Сентябрь 29, 2011, 13:21 »

Так было бы хорошо, но ф-ции установки принимают разные аргументы (см первый пост темы)
Так ты для массивов другой класс-шаблон сделай. Подмигивающий
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Сентябрь 29, 2011, 13:30 »

Так ты для массивов другой класс-шаблон сделай. Подмигивающий
Согласен, там вариантов совсем немного, можно перетерпеть. А вот как бы мне ф-ции "замаскировать" - чтобы не тащить связанные с OpenGL хедеры во все места где заполняются переменные?

Спасибо
Записан
BRE
Гость
« Ответ #11 : Сентябрь 29, 2011, 13:43 »

А вот как бы мне ф-ции "замаскировать" - чтобы не тащить связанные с OpenGL хедеры во все места где заполняются переменные?
В одном файле подключить gl-хедеры и определить все возможные типы через typedef.
А дальше уже инклюдить этот файл?
Но все равно при разворачивании шаблонов прототипы функций должны быть видны.
« Последнее редактирование: Сентябрь 29, 2011, 13:49 от BRE » Записан
vregess
Гость
« Ответ #12 : Сентябрь 30, 2011, 12:08 »

Может быть поможет cdiggins::any?
http://www.codeproject.com/KB/cpp/dynamic_typing.aspx
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Октябрь 01, 2011, 15:37 »

Может быть поможет cdiggins::any?
http://www.codeproject.com/KB/cpp/dynamic_typing.aspx
Спасибо, интересная статейка. Согласен с автором что в данном случае свой велосипед смотрится явно выгоднее. Я сделал так (обвязки, typedef и.т.п опускаю)

Код
C++ (Qt)
#include <QtGui>
#include <map>
#include <cassert>
 
struct CAbstractVar {
virtual ~CAbstractVar( void ) {}
};
 
template <class T>
struct CVar : public CAbstractVar {
T mData;
};
 
typedef std::map <const char *, CAbstractVar *> TVarMap;
 
template <class T>
T & GetVar( TVarMap & theMap, const char * name )
{
TVarMap::iterator it = theMap.find(name);
if (it != theMap.end()) {
assert(&typeid(*(it->second)) == &typeid(CVar <T>));
// assert(dynamic_cast <CVar <T> *> (it->second) != 0);  // или так
return ((CVar <T> *) it->second)->mData;
}
else {
CVar <T> * ptr = new CVar <T>;
theMap[name] = ptr;
return ptr->mData;
}
}
 
int main(int argc, char **argv)
{
(void) argc;
(void) argv;
 
TVarMap theMap;
GetVar<int> (theMap, "Int1") = 1;
int test = GetVar<int> (theMap, "Int1");
GetVar<float> (theMap, "Float1") = 2;
int test2 = GetVar<float> (theMap, "Int1");  // проверка на вылет
return 0;
}
 
А саму связку с OpenGL тупо через if(ы). Зато все остальное получается удобнее и короче.

Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.344 секунд. Запросов: 23.