Хочется странного, а именно вычисления placeholder'ов (_1, _2 и т.д.) без композиции функторов. Проблема поднималась очень давно здесь, но решения так никто и не предложил. Ниже приводится законченный пример, который иллюстрирует ситуацию:
#include <boost/bind.hpp>
#include <boost/bind/protect.hpp>
#include <boost/function.hpp>
#include <iostream>
class f_runner
{
public:
void run(boost::function<void ()> f, bool deferred)
{
std::cout << "From runner " << (deferred ? "( deferred ): " : ": ");
f();
}
};
class h
{
public:
void handle(const std::string & a, const std::string & b)
{
std::cout << a << " - " << b;
}
};
template<class T>
void wrapper(T f)
{
f("a", "b");
}
int main(int argc, const char * const argv[])
{
f_runner runner;
h handler;
// What do we really need:
// runner.run(boost::bind(f, "arg1", "arg2"), true);
boost::function<void (const std::string &, const std::string &)> f =\
boost::bind(&h::handle, boost::ref(handler)
, _1
, _2);
boost::function<void (const std::string &, const std::string &)> run =\
boost::bind(&f_runner::run, boost::ref(runner)
, boost::protect(boost::bind(f
, _1
, _2)) // evaluation of _1 and _2 is needed , true);
wrapper(run);
return 0;
}
В выделенном фрагменте используется boost::protect, чтобы предотвратить композицию и для метода f_runner::run. Однако boost::protect предотвращает вычисление placeholder'ов. Есть ли какие-нибудь пути обхода сложившейся ситуации?
Здравствуйте, adalekin, Вы писали:
A>Доброго времени суток, коллеги!
A> // What do we really need: A> // runner.run(boost::bind(f, "arg1", "arg2"), true); A>
Здравствуйте, adalekin, Вы писали:
A>Доброго времени суток, коллеги!
A>Хочется странного, а именно вычисления placeholder'ов (_1, _2 и т.д.) без композиции функторов.
По сути, нужно забиндить функцию bind.
void foo(string a, string b, string c) { cout<<a<<b<<c; }
void bar(function<void()> f, bool b) { cout<<b; f(); }
void wrapper(function<void(string,string)> f) { f("a","b"); }
foo("a","+","b");
wrapper(bind(foo,_1,"+",_2));
bar(bind(foo,"b","+","a"),true);
wrapper(bind(bar,bind(bind,foo,_2,"+",_1),true);
Поскольку bind — перегруженная функция, возвра, и вообще там чёрт ногу сломит с типами, я решил сделать проще: написать своё
template<class R>
struct metabind
{
typedef R result_type;
template<class A1>
result_type operator()(A1 a1) const { return bind(a1); }
template<class A1, class A2>
result_type operator()(A1 a1, A2 a2) const { return bind(a1,a2); }
template<class A1, class A2, class A3>
result_type operator()(A1 a1, A2 a2, A3 a3) const { return bind(a1,a2,a3); }
template<class A1, class A2, class A3, class A4>
result_type operator()(A1 a1, A2 a2, A3 a3, A4 a4) const { return bind(a1,a2,a3,a4); }
template<class A1, class A2, class A3, class A4, class A5>
result_type operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const { return bind(a1,a2,a3,a4,a5); }
};
wrapper(bind(bar,bind(metabind<function<void(string,string)>(),foo,_2,"+",_1),true);
Теоретически, этот metabind там и так есть. Вопрос в том, как его правильно объявить
В теории все выглядит очень логично, даже эллегантно. Композиция bar и функтора, который вернет metabind, есть ровно то, что нужно — вычисляются _1 и _2, а bar получает функтор в качестве параметра.
Но заставить скомпилироваться этот код мне так и не удалось. MSVC++ в итоге отчаянно пытается увидеть во всей конструкции функтор без параметров.
error C2064: term does not evaluate to a function taking 0 arguments
Аналогичную ошибку выдает и gcc 4.4.3.
Похоже, что реализация bind к таким маневрам не приспособлена. Но сама идея "забиндить функцию bind" просто "ух"! Огромное спасибо!
Здравствуйте, adalekin, Вы писали:
A>Но заставить скомпилироваться этот код мне так и не удалось. MSVC++ в итоге отчаянно пытается увидеть во всей конструкции функтор без параметров.
A>Похоже, что реализация bind к таким маневрам не приспособлена. Но сама идея "забиндить функцию bind" просто "ух"! Огромное спасибо!
Всё приспособлено, только оно, как женщины и тетрис на девятом уровне: не прощают ошибок.
Надо было правильно тип указывать...
Здравствуйте, Кодт, Вы писали:
К> Всё приспособлено, только оно, как женщины и тетрис на девятом уровне: не прощают ошибок. К> Надо было правильно тип указывать...