Зачем нужен этот указатель при вызове std :: call_once ()?

В книге «Параллельность C ++ в действии» §3.3.1, когда вводится ленточная инициализация безопасной для потока класса с использованием std::call_once(), это дает следующий пример:

#include <mutex>

struct connection_info
{};

struct data_packet
{};

struct connection_handle
{
void send_data(data_packet const&)
{}
data_packet receive_data()
{
return data_packet();
}
};

struct remote_connection_manager
{
connection_handle open(connection_info const&)
{
return connection_handle();
}
} connection_manager;class X
{
private:
connection_info connection_details;
connection_handle connection;
std::once_flag connection_init_flag;

void open_connection()
{
connection=connection_manager.open(connection_details);
}
public:
X(connection_info const& connection_details_):
connection_details(connection_details_)
{}
void send_data(data_packet const& data)
{
std::call_once(connection_init_flag,&X::open_connection,this);
connection.send_data(data);
}
data_packet receive_data()
{
std::call_once(connection_init_flag,&X::open_connection,this);
return connection.receive_data();
}
};

int main()
{}

От его документ, третий параметр — это параметр, передаваемый в функцию X::open_connection(), Почему this указатель нужен здесь при звонке std::call_once() При условии X::open_connection() не имеет входного параметра?

std::call_once(connection_init_flag,&X::open_connection,this);

П.С .: Удаление this указатель вызовет ошибку C2064:

error C2064: term does not evaluate to a function taking 0 arguments


Обновлено: Эта проблема более подробно рассматривается в п. 4.2.1 книги «Параллельность C ++ в действии» при введении аналогичных функций, т.е. std::async:

Если первый аргумент (должен быть вторым для std::call_once) — указатель на функцию-член, второй аргумент (должен быть третьим для std::call_once) предоставляет объект, к которому применяется функция-член (либо напрямую, либо через указатель, либо в виде std::ref), а остальные аргументы передаются в качестве аргументов функции-члену. В противном случае второй (должен быть третьим для std::call_once) и последующие аргументы передаются в качестве аргументов функции или вызываемому объекту, указанному в качестве первого аргумента.

4

Решение

Зачем нужен этот указатель при вызове std :: call_once ()?

Так как open_connection является нестатическим членом данных. Это должно быть вызвано чем-то, и что-то является тем же экземпляром, на который указывает this (технически, нестатические функции-члены имеют неявный первый параметр для this.)

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

X x;
std::call_once(connection_init_flag, &X::open_connection, &x);
12

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

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

std::call_once(connection_init_flag, [&]{ open_connection(); } );
// or
std::call_once(connection_init_flag, [this]{ open_connection(); } );

Что также в точности эквивалентно:

std::call_once(connection_init_flag, [this]{ this->open_connection(); } );
5

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