Здравствуйте.
Вопрос такой: есть Action List со списком действий. Пользователь выбирает в базе данных поле, которому соответствует другое поле (строка) с названием действия. Как запустить действие из списка Action List, используя это название?
Здравствуйте, Kluev, Вы писали:
K>А что за действия то? "Наливай и пей" или "шагом марш"?
Действия разные, например — движение мыши в указанном напрвлении, запуск программ, в общем — разные функции API. То есть в Action Liste уже есть определенные действия, написаны их обрабаотчики. Мне нужно "сопоставить" этим обработчикам выбранные из списка комманды, которые могут называться как угодно, хоть "наливай и пей"
Здравствуйте, explorer, Вы писали:
E> Вопрос такой: есть Action List со списком действий. Пользователь выбирает в базе данных поле, которому соответствует другое поле (строка) с названием действия. Как запустить действие из списка Action List, используя это название?
Если я тебя правильно понял, и тебе необходимо вызывать функции, имена которых ты получаешь в runtime в виде строки, то это можно сделать так:
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <string>
#include <map>
#include <stdexcept>
#include <boost/function.hpp>
#include <boost/bind.hpp>
////////////////////////////////////////////////////////////////////////////////
using boost::function;
using boost::bind;
using namespace std;
////////////////////////////////////////////////////////////////////////////////
class executor
{
public:
typedef function<void()> command;
void register_command(const string& command_name, const command& cmd)
{
commands_[command_name] = cmd;
}
void unregister_command(const string& command_name)
{
commands_.erase(command_name);
}
command::result_type execute(const string& command_name)
{
command_map::const_iterator i(commands_.find(command_name));
if(commands_.end() != i)
return i->second();
else
throw logic_error("command is not registered");
}
private:
typedef map<string, command> command_map;
command_map commands_;
};
////////////////////////////////////////////////////////////////////////////////
void on_command_abc()
{
cout << "executing command \"abc\"\n";
}
void on_command_def()
{
cout << "executing command \"def\"\n";
}
struct some
{
void on_command_ghi()
{
cout << "executing command \"ghi\"\n";
}
void on_command_jkl()
{
cout << "executing command \"jkl\"\n";
}
};
////////////////////////////////////////////////////////////////////////////////
int main()
{
executor e;
// команды "abc" и "def" выполняют функции
e.register_command("abc", &on_command_abc);
e.register_command("def", &on_command_def);
// команды "ghi" и "jkl" выполняют функции-члены объекта s
some s;
e.register_command("ghi", bind(&some::on_command_ghi, &s));
e.register_command("jkl", bind(&some::on_command_jkl, &s));
e.execute("abc");
e.execute("def");
e.execute("ghi");
e.execute("jkl");
e.execute("cba"); // oops - такая команда не зарегистрирована
return 0;
}
////////////////////////////////////////////////////////////////////////////////
Здравствуйте, MaximE, Вы писали:
ME>Если я тебя правильно понял, и тебе необходимо вызывать функции, имена которых ты получаешь в runtime в виде строки, то это можно сделать так...
Совершенно верно! Это мне и нужно. Но у меня возник вопрос (прошу прощения, если он покажется глупым

), — я не совсем разобрался в вашем коде. Компилятор (Borland C++ builder 6) недоволен этими строками:
ME>#include <boost/function.hpp>
ME>#include <boost/bind.hpp>
И еще, если не трудно, объясните в двух словах работу класса executor.
Здравствуйте, explorer, Вы писали:
E>Совершенно верно! Это мне и нужно. Но у меня возник вопрос (прошу прощения, если он покажется глупым
), — я не совсем разобрался в вашем коде. Компилятор (Borland C++ builder 6) недоволен этими строками:
ME>>#include <boost/function.hpp>
ME>>#include <boost/bind.hpp>
Похоже, что у тебя не установлена библиотека boost. Ее можно скачать с
www.boost.org
Кроме того, так как ты используешь BCB, то видимо, надо использовать синтаксис не function<void()>, а function0<void>.
E>И еще, если не трудно, объясните в двух словах работу класса executor.
Имя command немного непродумано, надо его зареплейсить на handler (обработчик).
Класс executor — небольшая обертка (я бы сказал, комментарий

) над ассоциативным массивом commands_, в котором ключами являются строки (имена команд), а значениями — обработчики этих команд (boost::function<> — обобщенный указатель на функцию). Т.е. имея строчку мы можем попытаться вызвать связанный с этой строчкой обработчик, чем и занимается функция execute. Если commands_ не содержит элемента (обработчика) с таким ключом (строчкой), будет сгенерировано исключение. Соответственно, функция register_command() принимает строчку и обобщенный указатель на функцию, и помещает их в ассоциативный массив commands_. Функция unregister_command() принимает строчку и удаляют из массива элемент с данным ключом.
Здравствуйте, MaximE.
Огромное спасибо!!! Вы мне очень поиогли. Сегодня вечером скачаю библиотеку и буду разбираться.