std :: function и shared_ptr

Я использовал Функтор Локи некоторое время, и недавно я спросил вопрос об этом (до сих пор без ответа …)
Мне сказали использовать std :: function, но я предпочитаю реализацию Functor от Loki, поскольку он также работает со всевозможными указателями в качестве параметров (например, std :: 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?

7

Решение

использование 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 если вы не хотите копий.

6

Другие решения

использование 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 );
}

Живая демоверсия.

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

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 может быть более привлекательным снова.

1
По вопросам рекламы [email protected]