2013-12-16 17 views
7

Я использую Functor Loki какое-то время, и недавно я спросил об этом question (все еще без ответа ...) Мне сказали использовать функцию std :: function, но я предпочитаю реализацию Loki из Functor, так как он также работает со всеми видами указателей в качестве параметров (например, std :: shared_ptr).std :: function и shared_ptr

struct Toto 
{ 
    void foo(int param) 
    { 
     std::cout << "foo: " << param << std::endl; 
    } 
}; 

int 
main(int argc, const char** argv) 
{ 
    std::shared_ptr<Toto> ptr = std::make_shared<Toto>(); 

    Loki::Functor<void, LOKI_TYPELIST_1(int)> func(ptr, &Toto::foo); 

    func(1); 
} 

Есть ли способ сделать это с помощью std :: function?

ответ

6

Использование std::bind.

auto func = std::bind(&Toto::foo, ptr, std::placeholders::_1); 

здесь, func будет выведен к типу, который был возвращен из std::bind или, если вам не нравится auto вы можете использовать (и вы хотите использовать std::function)

std::function<void(int)> func = std::bind(&Toto::foo, 
ptr, std::placeholders::_1); 

Здесь std::function будет быть построены из результата std::bind. ptr будет скопирован на какой-либо объект, возвращенный с std::bind, однако вы можете использовать std::ref/std::cref, если вы не хотите копировать.

+1

Я не думаю, что это работает с 'shared_ptr', и если бы это было так, это не переоценило бы указатель при каждом вызове. Кроме того, обратите внимание, что эти однострочные шрифты выполняют совершенно разные вещи: 'bind()' не возвращает 'std :: function'. – Potatoswatter

+0

@Potatoswatter работает с 'shared_ptr'. Почему он должен переоценить? – ForEveR

+0

Ах, я пропустил тонкость концепции INVOKE. В действительности это делает копию и разыгрывания каждый раз. Я думал о конверсии. Тем не менее, обратите внимание, что 'auto' сохраняет статически-отправленный объект привязки, а не динамически отправленную' std :: function', и это совершенно разные вещи. – Potatoswatter

1

Использование std::bind.

struct Toto 
{ 
    void foo(int param) 
    { 
     std::cout << "foo: " << param << std::endl; 
    } 
}; 

int main() { 
    std::shared_ptr<Toto> ptr = std::make_shared<Toto>(); 
    std::function< void(int) > func(std::bind(&Toto::foo, 
     std::bind([ptr]() { return ptr.get(); }), 
     std::placeholders::_1 
    )); 

    func(1); 
} 

Live demo.

Edit: Внутренний bind с лямбда-выражения на самом деле не нужны, но я просто оставлю это здесь в качестве иллюстрации более продвинутого использования.

+0

Неизбираемый, извините. – chill

1

Если вы не хотите использовать std::bind, вариант заключается в использовании функции лямбды, что приводит к еще меньший код, и я лично считаю его более понятным:

auto func = [&ptr](int p){ ptr->foo(p); }; 

или без auto:

std::function<void(int)> func = [&ptr](int p){ ptr->foo(p); }; 

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

+0

Ничего себе, хороший трюк! И вы правы, это очень интуитивно. – Athanase

 Смежные вопросы

  • Нет связанных вопросов^_^