Могу ли я использовать boost::bind для хранения несвязанного объекта?

Могу ли я использовать boost::bind, чтобы результирующий объект функции хранил объект, который не объявлен в качестве аргумента связанной целевой функции? Например:

void Connect(const error_code& errorCode)
{
    ...
}

// Invokes Connect after 5 seconds.
void DelayedConnect()
{
    boost::shared_ptr<boost::asio::deadline_timer> timer =
        boost::make_shared<boost::asio::deadline_timer>(ioServiceFromSomewhere);

    timer->expires_from_now(
        boost::posix_time::seconds(5));

    // Here I would like to pass the smart pointer 'timer' to the 'bind function object'
    // so that the deadline_timer is kept alive, even if it is not an actual argument
    // to 'Connect'. Is this possible with the bind syntax or similar?
    timer->async_wait(
        boost::bind(&Connect, boost::asio::placeholders::error));
}

пс. Меня больше всего интересует уже существующий синтаксис для этого. Я знаю, что могу сделать собственный код, чтобы сделать это самостоятельно. Я также знаю, что могу поддерживать таймер вручную, но я бы хотел этого избежать.


person shadow_map    schedule 30.01.2017    source источник


Ответы (2)


Да, вы можете сделать это, привязав дополнительные параметры. Я часто делал это с asio, например. чтобы поддерживать буферы или другое состояние во время асинхронной операции.

Вы также можете получить доступ к этим дополнительным аргументам из обработчика впоследствии, расширив сигнатуру обработчика, чтобы использовать их:

void Connect(const error_code& errorCode, boost::shared_ptr<asio::deadline_timer> timer)
{
}

timer.async_wait(
    boost::bind(&Connect, boost::asio::placeholders::error, timer));
person Matthias247    schedule 30.01.2017
comment
Спасибо. Я тоже примерно так планирую. Есть ли у вас какие-либо предпочтения в отношении того, какие типы интеллектуальных указателей использовать в таких ситуациях (в рамках повышения и STL)? - person shadow_map; 30.01.2017
comment
Я использовал boost::shared_ptr и std::shared_ptr. Я предполагаю, что unqiue_ptr тоже может работать, если объект затем перемещается в объект обработчика. Но у меня нет опыта в этом, так как мне все равно нужен shared_ptr. - person Matthias247; 30.01.2017
comment
К сожалению, я получаю ошибки компиляции с компилятором Visual Studio 2012 при использовании дополнительных параметров, как было предложено: ошибка C2039: 'result_type': не является членом "глобального пространства имен" ошибка C2208: 'boost::_bi::type': нет члены, определенные с использованием этой ошибки типа C2825: «F»: должен быть классом или пространством имен, если за ним следует «::» - person shadow_map; 31.01.2017
comment
Кажется, что дополнительный параметр вызывает и перегружает bind, который принимает возвращаемый тип в качестве входных данных, поэтому возникает запутанная ошибка. Если я перехожу на использование boost::bind‹void›(&Connect, boost::asio::placeholders::error, timer), я получаю более четкое сообщение об ошибке, но только при фактическом вызове объекта связанной функции: error C2197: too много аргументов в пользу - person shadow_map; 31.01.2017
comment
Если это не сработает с boost::bind, вы также можете попробовать std::bind с std::bind(&Connect, std::placeholders::_1, timer). Извините, я понятия не имею об этом сообщении об ошибке - person Matthias247; 31.01.2017

Да, вы можете просто привязать «слишком много» параметров, и они не будут переданы базовому обработчику. См. Почему объекты, возвращаемые из привязки, игнорируют дополнительные аргументы?

Это нормально, если только вам не нужно «общаться» с объектом таймера изнутри Connect.

PS. Кроме того, не забудьте ожидать завершения таймера с помощью operation_abandoned, когда таймер будет уничтожен.

person sehe    schedule 30.01.2017
comment
В порядке. Думаю, я могу поговорить с такой вещью, как Matthias247, описанной в предыдущем ответе. Хорошее замечание по поводу operation_abandoned. - person shadow_map; 30.01.2017