Пытаюсь реализовать аналог Q_PROPERTY.
class base {
public:
typedef bool(*sp)(int);
typedef int(*gp)();
typedef std::pair<sp, gp> prop;
typedef std::map<std::string, prop> PropertyMap;
public:
base() {}
virtual ~base() {}
public:
bool setProperty(const char* name, int value) {
std::string str(name);
PropertyMap::const_iterator i = propMap.find(str);
((i->second).first)(value);
return true;
}
int property(const char* name) const {
std::string str(name);
PropertyMap::const_iterator i = propMap.find(str);
return ((i->second).second)();
}
protected:
PropertyMap propMap;
bool register_property(const char* name, sp setprop, gp getprop) {
return propMap.insert(std::make_pair(std::string(name), prop(setprop, getprop))).second;
}
};
class base1 : public base
{
public:
base1() {
//register_property("TEST",&base1::setTestProp, &base1::getTestProp()); //< ??? Проблема здесь
}
bool setTestProp(int val) {
return true;
}
int getTestProp() {
return 125;
}
};
static int call_getTestProp(base1& param) {
return param.getTestProp();
}
и передавать указатель уже этого методаПосмотри на boost::bind.
Выдает следущую ошибку
main.cpp:80: error: no matching function for call to ‘base1::register_property(const char [5], boost::_bi::bind_t<bool (&)(int), boost::_mfi::dm<bool ()(int), base1>, boost::_bi::list1<boost::_bi::value<base1*> > >, boost::_bi::bind_t<int, boost::_mfi::mf0<int, base1>, boost::_bi::list1<boost::_bi::value<base1*> > >)’
main.cpp:67: note: candidates are: bool base::register_property(const char*, bool (*)(int), int (*)())
Посмотри, например, вот на это: http://www.progz.ru/forum/index.php?showtopic=27073&st=0
Набросаю прямо здесь небольшой пример:
typedef boost::function<bool (int)> SetFunc;
typedef boost::function<int ()> GetFunc;
bool register_property(const char* name, SetFunc setprop, GetFunc getprop)
{
...
}
class base
{
public:
base();
virtual ~base();
typedef function<bool (int)> SetFunc;
typedef function<int ()> GetFunc;
typedef pair<SetFunc, GetFunc> Set_Get_Pair;
typedef map<string, Set_Get_Pair> PropertyMap;
bool setProperty(const char* name, int value) {
std::string str(name);
PropertyMap::const_iterator i = propMap.find(str);
((i->second).first)(value);
return true;
}
int property(const char* name) const {
string str(name);
PropertyMap::const_iterator i = propMap.find(str);
return ((i->second).second)();
}
protected:
PropertyMap propMap;
bool register_property(const char* name, SetFunc setprop, GetFunc getprop) {
return propMap.insert(make_pair(string(name), Set_Get_Pair(setprop, getprop))).second;
}
};
class device : public base
{
public:
device() {
SetFunc sf = bind(&device::setTestProp, this); // ошибка!!!!!
// GetFunc gf = bind(&device::getTestProp);
// register_property("Test", sf, gf);
}
bool setTestProp(int /*val*/) {
return true;
}
int getTestProp() {
return 125;
}
};
Более подробный рабочий пример:
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>
class Base
{
public:
typedef boost::function<bool (int)> SetFunc;
typedef boost::function<int ()> GetFunc;
Base() : m_value( 0 ) {}
bool set( int val )
{
std::cout << "set=" << val << std::endl;
m_value = val;
return true;
}
int get()
{
return m_value;
}
private:
int m_value;
};
int main( int, char ** )
{
Base b;
Base::SetFunc sf = boost::bind( &Base::set, &b, _1 );
Base::GetFunc gf = boost::bind( &Base::get, &b );
std::cout << "get=" << gf() << std::endl;
sf( 100 );
std::cout << "get=" << gf() << std::endl;
return 0;
}
BRE, спасибо огромнейшее. Все получилось.
Осталось отвязаться от конкретных типов. Пока не понял что лучше использовать - boost::any или boost::variant ?
Как обобщу, выложу готовый пример. Может еще кому пригодится
ЗЫ. Тему лучше перенести в boost.
Вот что в результате получилось.
#include <map>
#include <string>
#include <boost/function.hpp>
#include <boost/bind/bind.hpp>
#include <boost/variant.hpp>
using namespace std;
using namespace boost;
/// тип свойства
typedef boost::variant<int, string, double> Property_t;
/**
* \def REGISTER_PROPERTY(NAME, SETFUNC, GETFUNC)
* \brief регистрация свойства экземпляра класса.
*
* \var NAME - имя свойства
* \var SETFUNC - указатель на функцию установки свойства
* \var GETFUNC - указатель на функцию чтения свойства
*/
#define REGISTER_PROPERTY(NAME, SETFUNC, GETFUNC) { \
register_property( NAME, boost::bind(&SETFUNC, this, _1), boost::bind(&GETFUNC, this) ); \
}
class Property
{
public:
Property() {} //!< Конструктор
virtual ~Property() //!< Деструктор. Чистит все списки свойств
{
// а как память коректно очистить ???
propMap.clear();
}
public:
/// Тип указателя на процедуру установки свойства
typedef boost::function< bool (Property_t) > SetFunc;
/// Тип указателя на процедуру чтения свойства
typedef boost::function< Property_t () > GetFunc;
/// Тип пары указателей на сетер и гетер
typedef std::pair< SetFunc, GetFunc > Set_Get_Pair;
/// Тип отображения свойств
typedef std::map< string, Set_Get_Pair > PropertyMap;
public:
/**
* \brief Установить свойство.
*
* \var name - имя свойства
* \var value - значение
* \return true при успешной установке свойства, иначе false.
* \warning Если свойство не найдено, генерируется исключение
*/
bool setProperty(const char* name, Property_t value)
{
std::string str(name);
PropertyMap::const_iterator i = propMap.find(str);
if( i == propMap.end() ) {
throw std::runtime_error("[setProperty] неизвестное свойство");
}
return ((i->second).first)(value);
}
/**
* \brief Считать свойство.
*
* \var name - имя свойства
* \return значение свойства
* \warning Если свойство не найдено, генерируется исключение
*/
Property_t property(const char* name) const {
std::string str(name);
PropertyMap::const_iterator i = propMap.find(str);
if( i == propMap.end() ) {
throw std::runtime_error("[property] неизвестное свойство");
}
return ((i->second).second)();
}
protected:
PropertyMap propMap; //!< отображение свойств
/**
* \brief Зарегистрировать свойство.
* \return true при удачной регистрации, иначе false
*/
bool register_property(const char* name, SetFunc setprop, GetFunc getprop) {
return propMap.insert(std::make_pair(string(name), Set_Get_Pair(setprop, getprop))).second;
}
};
class Test1 : public Property
{
public:
Test1() {
REGISTER_PROPERTY("Test", Test1::setTestProp, Test1::getTestProp);
}
bool setTestProp(Property_t /*val*/) {
return true;
}
Property_t getTestProp() {
return 125;
}
};
class Test2 : public Property
{
public:
Test2() {
REGISTER_PROPERTY("Test", Test2::setTestProp2, Test2::getTestProp2);
}
bool setTestProp2(Property_t /*val*/) {
return true;
}
Property_t getTestProp2() {
return "string";
}
};
class Test3 : public Property
{
public:
Test3() {
REGISTER_PROPERTY("Test", Test3::setTestProp3, Test3::getTestProp3);
}
bool setTestProp3(Property_t /*val*/) {
return true;
}
Property_t getTestProp3() {
return 1.89;
}
};
int main(int /*argc*/, char** /*argc*/)
{
Property* b[] = { new Test1, new Test2, new Test3 };
for(int i = 0; i != 3; i++ )
cout <<"Property_t = " << b[i]->property("Test") << std::endl;
return EXIT_SUCCESS;
}
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)