Преобразование std :: function <void (string, string)> в универсальный std :: function <void ()> - PullRequest
1 голос
/ 24 октября 2011

Я пробую некоторые функции c ++ 0x (под gcc 4.5):

Я знаю, что можно преобразовать std::function<void(string, string)> в std::function<void()>, когда аргументы указаны при компиляции; но возможно ли это, когда аргументы передаются во время выполнения?

#include <iostream>
#include <utility>
#include <string>

using namespace std;
using namespace placeholders;

class Print{

  public:
    void print1(string s1, string s2){ cout<<"s1 : "<<s1<<" s2 : "<<s2<<endl;}
    void print2(string s1){ cout<<"s1 : "<<s1<<endl;}

};

Print p  =  Print();

function<void(string, string)> f1(bind(&Print::print1, &p, _1, _2));

function<void()> f = f1;

Я получаю эти ошибки:

/usr/include/c++/4.5/functional:2103:6:   instantiated from ‘std::function<_Res(_ArgTypes ...)>::function(_Functor, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type) [with _Functor = std::function<void(std::basic_string<char>, std::basic_string<char>)>, _Res = void, _ArgTypes = {}, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type = std::function<void()>::_Useless]’
../src/Cpp0x_test.cpp:345:34:   instantiated from here
/usr/include/c++/4.5/functional:1713:9: error: no match for call to ‘(std::function<void(std::basic_string<char>, std::basic_string<char>)>) ()’
/usr/include/c++/4.5/functional:2111:5: note: candidate is: _Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = void, _ArgTypes = {std::basic_string<char>, std::basic_string<char>}]

На самом деле мне нужно сделать:

function<void(string, string)> f1(bind(&Print::print1, &p, _1, _2));
function<void(string)> f2(bind(&Print::print2, &p, _1));

function<void()> fx1 = f1;
function<void()> fx2 = f2;

std::vector<function<void()> > vec;

vec.push_back(fx1);
vec.push_back(fx2);

//then, later

function<void()> call1 = vec[0];
function<void()> call2 = vec[1];

call1("test1", "test2");
call2("test3");

Ответы [ 3 ]

3 голосов
/ 24 октября 2011

Вопрос на самом деле не имеет смысла.

Я знаю, что можно преобразовать std::function<void(string, string)> в std::function<void()>, когда аргументы указаны при компиляции;но возможно ли это, когда аргументы передаются во время выполнения?

Если вы говорите об этом, чтобы установить аргументы "при компиляции":

string arg1,arg2;
function<void()> f = bind(f1,arg1,arg2); // f = [=] { f1(arg1,arg2); };

это фактически делаетпривязка во время выполнения.Независимо от того, какое значение имеют эти аргументы при вызове bind, даже если они установлены во время выполнения, скажем, из пользовательского ввода, вызывающий f() будет использовать эти значения времени выполнения.

Возможно, вы имеете в виду, что приведенный выше код связывает f1 до значений arg1 и arg2 во время вызова привязки, и то, что изменение значений объектов, используемых в bind позже, не влияет на значения, используемые в вызовах f().Есть способ обойти это:

string arg1,arg2;
function<void()> f =
  bind(f1,std::ref(arg1),std::ref(arg2)); // f = [&,f1] { f1(arg1,arg2); };

Это заставляет f хранить ссылки на объекты, а не только статическое значение, используемое во время вызова bind.Теперь вы можете назначать новые значения arg1 и arg2, и когда вызывается f(), будут использоваться новые значения.Обратите внимание, что вы должны убедиться, что ссылки, хранящиеся в f, остаются действительными и не становятся висячими ссылками, пока можно вызывать f.

function<void(string)> foo = [](string s){ cout << s; };
string arg = "Hello,";
function<void()> bar = bind(foo,ref(arg)); // bar = [=,&arg] { foo(arg); };
bar(); // prints "Hello,"
arg = " World!"
bar(); // prints " World!"
2 голосов
/ 24 октября 2011

Возможно использование bind aswell:

string arg1, arg2;

function<void()> f(bind(f1, arg1, arg2));

f(); // calls f1(arg1, arg2) with their values at the time of bind
1 голос
/ 25 октября 2011

Давайте посмотрим, понимаю ли я ваше требование.

Почему бы вам просто не сохранить аргументы в векторе вместо функций?

std::vector<std::tuple<std::string,std::string>> v;
v.push_back(std::make_tuple("a", "b")); // repeat

// Later that day...
for(auto& t : v) {
    f(get<0>(t), get<1>(t));
}
...