是否可以使用智能ptr或boost侵入式ptr作为;无效*标签";用C+;编写的gRPC异步服务器中的值+; 我在C++中编写了一个异步GRPC服务器(在Windows上)。我想对“tag”值使用boost侵入式指针类型-指向RPC处理程序对象的指针,该对象在完成队列“Next()”方法期间返回

是否可以使用智能ptr或boost侵入式ptr作为;无效*标签";用C+;编写的gRPC异步服务器中的值+; 我在C++中编写了一个异步GRPC服务器(在Windows上)。我想对“tag”值使用boost侵入式指针类型-指向RPC处理程序对象的指针,该对象在完成队列“Next()”方法期间返回,c++,asynchronous,boost,grpc,C++,Asynchronous,Boost,Grpc,gRPC异步服务需要将void*传递给处理程序对象,以便在关联事件发生时调用处理程序。问题是,我无法找到一种方法来将boost侵入式指针转换为void*,从而保留并使用引用计数 可能吗?或者只有当我将指针传递给的方法需要一个boost指针时,它才会起作用吗?假设我们有一个第三方库,它接受静态回调函数,可以使用void*userdata来传递用户定义的状态: namespace SomeAPI { typedef void(*Callback)(int, void* userdata);

gRPC异步服务需要将void*传递给处理程序对象,以便在关联事件发生时调用处理程序。问题是,我无法找到一种方法来将boost侵入式指针转换为void*,从而保留并使用引用计数


可能吗?或者只有当我将指针传递给的方法需要一个boost指针时,它才会起作用吗?

假设我们有一个第三方库,它接受静态回调函数,可以使用
void*
userdata来传递用户定义的状态:

namespace SomeAPI {
    typedef void(*Callback)(int, void* userdata);

    struct Registration;

    Registration const* register_callback(Callback cb, void* userdata);
    size_t deregister_callback(Callback cb, void* userdata);
    void some_operation_invoking_callbacks();
}
此伪API的最低限度实现是,例如:

struct Registration {
    Callback cb;
    void* userdata;
};
std::list<Registration> s_callbacks;

Registration const* register_callback(Callback cb, void* userdata) {
    s_callbacks.push_back({cb, userdata});
    return &s_callbacks.back();
}

size_t deregister_callback(Callback cb, void* userdata) {
    auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
    s_callbacks.remove_if([&](Registration const& r) {
        return std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
    });
    return oldsize - s_callbacks.size();
}

void some_operation_invoking_callbacks() {
    static int s_counter = 0;
    for (auto& reg : s_callbacks) {
        reg.cb(++s_counter, reg.userdata);
    }
}
现在,让我们来练习一下客户机:

int main() {
    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();
}
 ------- operation start
State::foo with i:1 and greeting:"Foo"
 ------- operation start
State::foo with i:2 and greeting:"Foo"
State::foo with i:3 and greeting:"Bar"
~MyClient (Bar)
 ------- operation start
State::foo with i:4 and greeting:"Foo"
State::foo with i:5 and greeting:"Bar"
~State (Bar)
~MyClient (Foo)
~State (Foo)
#include <memory>
#include <list>
#include <string>
#include <iostream>
#include <iomanip>

namespace SomeAPI {
    using Callback = void(*)(int, void* userdata);

    struct Registration {
        Callback cb;
        void* userdata;
    };
    std::list<Registration> s_callbacks;

    Registration const* register_callback(Callback cb, void* userdata) {
        s_callbacks.push_back({cb, userdata});
        return &s_callbacks.back();
    }

    size_t deregister_callback(Callback cb, void* userdata) {
        auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
        s_callbacks.remove_if([&](Registration const& r) {
            return std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
        });
        return oldsize - s_callbacks.size();
    }

    void some_operation_invoking_callbacks() {
        static int s_counter = 0;
        for (auto& reg : s_callbacks) {
            reg.cb(++s_counter, reg.userdata);
        }
    }
}

struct MyClient {
    struct State {
        std::string greeting;

        void foo(int i) {
            std::cout
                << "State::foo with i:" << i
                << " and greeting:" << std::quoted(greeting)
                << "\n";
        }
    };
    using SharedState = std::shared_ptr<State>;
    SharedState state_;

    MyClient(std::string g) : state_(std::make_shared<State>(State{g})) {
        SomeAPI::register_callback(static_handler, &state_);
    }

    ~MyClient() noexcept {
        SomeAPI::deregister_callback(static_handler, &state_);
    }

    static void static_handler(int i, void* userdata) {
        auto& state = *static_cast<SharedState*>(userdata);
        state->foo(i);
    }
};

int main() {
    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();
}
#include <memory>
#include <list>
#include <string>
#include <iostream>
#include <iomanip>

namespace SomeAPI {
    enum { TEARDOWN_MAGIC_VALUE = -1 };
    using Callback = void(*)(int, void* userdata);

    struct Registration {
        Callback cb;
        void* userdata;
    };
    std::list<Registration> s_callbacks;

    Registration const* register_callback(Callback cb, void* userdata) {
        s_callbacks.push_back({cb, userdata});
        return &s_callbacks.back();
    }

    size_t deregister_callback(Callback cb, void* userdata) {
        auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
        s_callbacks.remove_if([&](Registration const& r) {
            bool const matched = std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
            if (matched) {
                r.cb(TEARDOWN_MAGIC_VALUE, r.userdata);
            }
            return matched;
        });
        return oldsize - s_callbacks.size();
    }

    void some_operation_invoking_callbacks() {
        static int s_counter = 0;
        for (auto& reg : s_callbacks) {
            reg.cb(++s_counter, reg.userdata);
        }
    }

    void InitAPI() {}
    void ShutdownAPI() {
        for (auto it = s_callbacks.begin(); it != s_callbacks.end();) {
            it->cb(TEARDOWN_MAGIC_VALUE, it->userdata);
            it = s_callbacks.erase(it);
        }
    }
}

struct MyClient {
    struct State {
        std::string greeting;
        State(std::string g) : greeting(std::move(g)) {}

        void foo(int i) {
            std::cout
                << "State::foo with i:" << i
                << " and greeting:" << std::quoted(greeting)
                << "\n";
        }

        ~State() noexcept {
            std::cout << "~State (" << greeting << ")\n";
        }
    };
    using SharedState = std::shared_ptr<State>;
    SharedState state_;

    MyClient(std::string g) : state_(std::make_shared<State>(std::move(g))) {
        SomeAPI::register_callback(static_handler, new SharedState(state_));
    }

    ~MyClient() {
        std::cout << "~MyClient (" << state_->greeting << ")\n";
    }

    static void static_handler(int i, void* userdata) {
        auto* sharedstate = static_cast<SharedState*>(userdata);
        if (i == SomeAPI::TEARDOWN_MAGIC_VALUE) {
            delete sharedstate; // decreases refcount
            return;
        } else {
            (*sharedstate)->foo(i);
        }
    }
};

int main() {
    SomeAPI::InitAPI();

    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    SomeAPI::ShutdownAPI();
}
紧绳法 如果实际上希望将所有权传递给API,即即使
客户机
实例消失,API仍保持状态,那么根据定义,您将泄漏该状态

唯一的解决方案是,如果API有某种回调来发出它应该清理的信号。我从未见过这样的API设计,但以下是它的外观:

enum { TEARDOWN_MAGIC_VALUE = -1 };
void InitAPI() {}
void ShutdownAPI() {
    for (auto it = s_callbacks.begin(); it != s_callbacks.end();) {
        it->cb(TEARDOWN_MAGIC_VALUE, it->userdata);
        it = s_callbacks.erase(it);
    }
}
现在,我们可以将
共享\u ptr
的动态分配副本作为用户数据传递给回调(而不是指向共享指针所属副本的原始指针):

请注意,由于
SomeAPI
现在具有共享指针的副本,因此refcount已增加。事实上,我们不必再注销回调,因为状态将保持有效,直到
SomeAPI
实际关闭:

static void static_handler(int i, void* userdata) {
    auto* sharedstate = static_cast<SharedState*>(userdata);
    if (i == SomeAPI::TEARDOWN_MAGIC_VALUE) {
        delete sharedstate; // decreases refcount
        return;
    } else {
        (*sharedstate)->foo(i);
    }
}
通过对析构函数的一些巧妙跟踪,您可以验证
状态
的生存期现在实际上由
ShutdownAPI
管理/共享:

int main() {
    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();
}
 ------- operation start
State::foo with i:1 and greeting:"Foo"
 ------- operation start
State::foo with i:2 and greeting:"Foo"
State::foo with i:3 and greeting:"Bar"
~MyClient (Bar)
 ------- operation start
State::foo with i:4 and greeting:"Foo"
State::foo with i:5 and greeting:"Bar"
~State (Bar)
~MyClient (Foo)
~State (Foo)
#include <memory>
#include <list>
#include <string>
#include <iostream>
#include <iomanip>

namespace SomeAPI {
    using Callback = void(*)(int, void* userdata);

    struct Registration {
        Callback cb;
        void* userdata;
    };
    std::list<Registration> s_callbacks;

    Registration const* register_callback(Callback cb, void* userdata) {
        s_callbacks.push_back({cb, userdata});
        return &s_callbacks.back();
    }

    size_t deregister_callback(Callback cb, void* userdata) {
        auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
        s_callbacks.remove_if([&](Registration const& r) {
            return std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
        });
        return oldsize - s_callbacks.size();
    }

    void some_operation_invoking_callbacks() {
        static int s_counter = 0;
        for (auto& reg : s_callbacks) {
            reg.cb(++s_counter, reg.userdata);
        }
    }
}

struct MyClient {
    struct State {
        std::string greeting;

        void foo(int i) {
            std::cout
                << "State::foo with i:" << i
                << " and greeting:" << std::quoted(greeting)
                << "\n";
        }
    };
    using SharedState = std::shared_ptr<State>;
    SharedState state_;

    MyClient(std::string g) : state_(std::make_shared<State>(State{g})) {
        SomeAPI::register_callback(static_handler, &state_);
    }

    ~MyClient() noexcept {
        SomeAPI::deregister_callback(static_handler, &state_);
    }

    static void static_handler(int i, void* userdata) {
        auto& state = *static_cast<SharedState*>(userdata);
        state->foo(i);
    }
};

int main() {
    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();
}
#include <memory>
#include <list>
#include <string>
#include <iostream>
#include <iomanip>

namespace SomeAPI {
    enum { TEARDOWN_MAGIC_VALUE = -1 };
    using Callback = void(*)(int, void* userdata);

    struct Registration {
        Callback cb;
        void* userdata;
    };
    std::list<Registration> s_callbacks;

    Registration const* register_callback(Callback cb, void* userdata) {
        s_callbacks.push_back({cb, userdata});
        return &s_callbacks.back();
    }

    size_t deregister_callback(Callback cb, void* userdata) {
        auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
        s_callbacks.remove_if([&](Registration const& r) {
            bool const matched = std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
            if (matched) {
                r.cb(TEARDOWN_MAGIC_VALUE, r.userdata);
            }
            return matched;
        });
        return oldsize - s_callbacks.size();
    }

    void some_operation_invoking_callbacks() {
        static int s_counter = 0;
        for (auto& reg : s_callbacks) {
            reg.cb(++s_counter, reg.userdata);
        }
    }

    void InitAPI() {}
    void ShutdownAPI() {
        for (auto it = s_callbacks.begin(); it != s_callbacks.end();) {
            it->cb(TEARDOWN_MAGIC_VALUE, it->userdata);
            it = s_callbacks.erase(it);
        }
    }
}

struct MyClient {
    struct State {
        std::string greeting;
        State(std::string g) : greeting(std::move(g)) {}

        void foo(int i) {
            std::cout
                << "State::foo with i:" << i
                << " and greeting:" << std::quoted(greeting)
                << "\n";
        }

        ~State() noexcept {
            std::cout << "~State (" << greeting << ")\n";
        }
    };
    using SharedState = std::shared_ptr<State>;
    SharedState state_;

    MyClient(std::string g) : state_(std::make_shared<State>(std::move(g))) {
        SomeAPI::register_callback(static_handler, new SharedState(state_));
    }

    ~MyClient() {
        std::cout << "~MyClient (" << state_->greeting << ")\n";
    }

    static void static_handler(int i, void* userdata) {
        auto* sharedstate = static_cast<SharedState*>(userdata);
        if (i == SomeAPI::TEARDOWN_MAGIC_VALUE) {
            delete sharedstate; // decreases refcount
            return;
        } else {
            (*sharedstate)->foo(i);
        }
    }
};

int main() {
    SomeAPI::InitAPI();

    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    SomeAPI::ShutdownAPI();
}
完整列表(经典)

int main() {
    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();
}
 ------- operation start
State::foo with i:1 and greeting:"Foo"
 ------- operation start
State::foo with i:2 and greeting:"Foo"
State::foo with i:3 and greeting:"Bar"
~MyClient (Bar)
 ------- operation start
State::foo with i:4 and greeting:"Foo"
State::foo with i:5 and greeting:"Bar"
~State (Bar)
~MyClient (Foo)
~State (Foo)
#include <memory>
#include <list>
#include <string>
#include <iostream>
#include <iomanip>

namespace SomeAPI {
    using Callback = void(*)(int, void* userdata);

    struct Registration {
        Callback cb;
        void* userdata;
    };
    std::list<Registration> s_callbacks;

    Registration const* register_callback(Callback cb, void* userdata) {
        s_callbacks.push_back({cb, userdata});
        return &s_callbacks.back();
    }

    size_t deregister_callback(Callback cb, void* userdata) {
        auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
        s_callbacks.remove_if([&](Registration const& r) {
            return std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
        });
        return oldsize - s_callbacks.size();
    }

    void some_operation_invoking_callbacks() {
        static int s_counter = 0;
        for (auto& reg : s_callbacks) {
            reg.cb(++s_counter, reg.userdata);
        }
    }
}

struct MyClient {
    struct State {
        std::string greeting;

        void foo(int i) {
            std::cout
                << "State::foo with i:" << i
                << " and greeting:" << std::quoted(greeting)
                << "\n";
        }
    };
    using SharedState = std::shared_ptr<State>;
    SharedState state_;

    MyClient(std::string g) : state_(std::make_shared<State>(State{g})) {
        SomeAPI::register_callback(static_handler, &state_);
    }

    ~MyClient() noexcept {
        SomeAPI::deregister_callback(static_handler, &state_);
    }

    static void static_handler(int i, void* userdata) {
        auto& state = *static_cast<SharedState*>(userdata);
        state->foo(i);
    }
};

int main() {
    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();
}
#include <memory>
#include <list>
#include <string>
#include <iostream>
#include <iomanip>

namespace SomeAPI {
    enum { TEARDOWN_MAGIC_VALUE = -1 };
    using Callback = void(*)(int, void* userdata);

    struct Registration {
        Callback cb;
        void* userdata;
    };
    std::list<Registration> s_callbacks;

    Registration const* register_callback(Callback cb, void* userdata) {
        s_callbacks.push_back({cb, userdata});
        return &s_callbacks.back();
    }

    size_t deregister_callback(Callback cb, void* userdata) {
        auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
        s_callbacks.remove_if([&](Registration const& r) {
            bool const matched = std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
            if (matched) {
                r.cb(TEARDOWN_MAGIC_VALUE, r.userdata);
            }
            return matched;
        });
        return oldsize - s_callbacks.size();
    }

    void some_operation_invoking_callbacks() {
        static int s_counter = 0;
        for (auto& reg : s_callbacks) {
            reg.cb(++s_counter, reg.userdata);
        }
    }

    void InitAPI() {}
    void ShutdownAPI() {
        for (auto it = s_callbacks.begin(); it != s_callbacks.end();) {
            it->cb(TEARDOWN_MAGIC_VALUE, it->userdata);
            it = s_callbacks.erase(it);
        }
    }
}

struct MyClient {
    struct State {
        std::string greeting;
        State(std::string g) : greeting(std::move(g)) {}

        void foo(int i) {
            std::cout
                << "State::foo with i:" << i
                << " and greeting:" << std::quoted(greeting)
                << "\n";
        }

        ~State() noexcept {
            std::cout << "~State (" << greeting << ")\n";
        }
    };
    using SharedState = std::shared_ptr<State>;
    SharedState state_;

    MyClient(std::string g) : state_(std::make_shared<State>(std::move(g))) {
        SomeAPI::register_callback(static_handler, new SharedState(state_));
    }

    ~MyClient() {
        std::cout << "~MyClient (" << state_->greeting << ")\n";
    }

    static void static_handler(int i, void* userdata) {
        auto* sharedstate = static_cast<SharedState*>(userdata);
        if (i == SomeAPI::TEARDOWN_MAGIC_VALUE) {
            delete sharedstate; // decreases refcount
            return;
        } else {
            (*sharedstate)->foo(i);
        }
    }
};

int main() {
    SomeAPI::InitAPI();

    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    SomeAPI::ShutdownAPI();
}
#包括
#包括
#包括
#包括
#包括
名称空间SomeAPI{
使用Callback=void(*)(int,void*userdata);
结构注册{
回调cb;
void*用户数据;
};
std::列出s_回调;
注册常量*注册\回调(回调cb,无效*用户数据){
s_回调。push_back({cb,userdata});
return&s_callbacks.back();
}
大小\u t取消注册\u回调(回调cb,void*userdata){
auto oldsize=s_callbacks.size();//c++20不需要这样做
s_回调。删除_if([&](注册常量&r){
返回std::tie(r.cb,r.userdata)==std::tie(cb,userdata);
});
返回oldsize-s_回调.size();
}
取消某些调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用调用{
静态int s_计数器=0;
用于(自动®;s\U回调){
注册cb(++s_计数器,注册用户数据);
}
}
}
结构MyClient{
结构状态{
字符串问候语;
空富(内部一){
标准::cout

假设我们有一个采用静态回调函数的第三方库,它可以使用
void*
userdata传递用户定义的状态:

namespace SomeAPI {
    typedef void(*Callback)(int, void* userdata);

    struct Registration;

    Registration const* register_callback(Callback cb, void* userdata);
    size_t deregister_callback(Callback cb, void* userdata);
    void some_operation_invoking_callbacks();
}
此伪API的最低限度实现是,例如:

struct Registration {
    Callback cb;
    void* userdata;
};
std::list<Registration> s_callbacks;

Registration const* register_callback(Callback cb, void* userdata) {
    s_callbacks.push_back({cb, userdata});
    return &s_callbacks.back();
}

size_t deregister_callback(Callback cb, void* userdata) {
    auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
    s_callbacks.remove_if([&](Registration const& r) {
        return std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
    });
    return oldsize - s_callbacks.size();
}

void some_operation_invoking_callbacks() {
    static int s_counter = 0;
    for (auto& reg : s_callbacks) {
        reg.cb(++s_counter, reg.userdata);
    }
}
现在,让我们来练习一下客户机:

int main() {
    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();
}
 ------- operation start
State::foo with i:1 and greeting:"Foo"
 ------- operation start
State::foo with i:2 and greeting:"Foo"
State::foo with i:3 and greeting:"Bar"
~MyClient (Bar)
 ------- operation start
State::foo with i:4 and greeting:"Foo"
State::foo with i:5 and greeting:"Bar"
~State (Bar)
~MyClient (Foo)
~State (Foo)
#include <memory>
#include <list>
#include <string>
#include <iostream>
#include <iomanip>

namespace SomeAPI {
    using Callback = void(*)(int, void* userdata);

    struct Registration {
        Callback cb;
        void* userdata;
    };
    std::list<Registration> s_callbacks;

    Registration const* register_callback(Callback cb, void* userdata) {
        s_callbacks.push_back({cb, userdata});
        return &s_callbacks.back();
    }

    size_t deregister_callback(Callback cb, void* userdata) {
        auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
        s_callbacks.remove_if([&](Registration const& r) {
            return std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
        });
        return oldsize - s_callbacks.size();
    }

    void some_operation_invoking_callbacks() {
        static int s_counter = 0;
        for (auto& reg : s_callbacks) {
            reg.cb(++s_counter, reg.userdata);
        }
    }
}

struct MyClient {
    struct State {
        std::string greeting;

        void foo(int i) {
            std::cout
                << "State::foo with i:" << i
                << " and greeting:" << std::quoted(greeting)
                << "\n";
        }
    };
    using SharedState = std::shared_ptr<State>;
    SharedState state_;

    MyClient(std::string g) : state_(std::make_shared<State>(State{g})) {
        SomeAPI::register_callback(static_handler, &state_);
    }

    ~MyClient() noexcept {
        SomeAPI::deregister_callback(static_handler, &state_);
    }

    static void static_handler(int i, void* userdata) {
        auto& state = *static_cast<SharedState*>(userdata);
        state->foo(i);
    }
};

int main() {
    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();
}
#include <memory>
#include <list>
#include <string>
#include <iostream>
#include <iomanip>

namespace SomeAPI {
    enum { TEARDOWN_MAGIC_VALUE = -1 };
    using Callback = void(*)(int, void* userdata);

    struct Registration {
        Callback cb;
        void* userdata;
    };
    std::list<Registration> s_callbacks;

    Registration const* register_callback(Callback cb, void* userdata) {
        s_callbacks.push_back({cb, userdata});
        return &s_callbacks.back();
    }

    size_t deregister_callback(Callback cb, void* userdata) {
        auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
        s_callbacks.remove_if([&](Registration const& r) {
            bool const matched = std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
            if (matched) {
                r.cb(TEARDOWN_MAGIC_VALUE, r.userdata);
            }
            return matched;
        });
        return oldsize - s_callbacks.size();
    }

    void some_operation_invoking_callbacks() {
        static int s_counter = 0;
        for (auto& reg : s_callbacks) {
            reg.cb(++s_counter, reg.userdata);
        }
    }

    void InitAPI() {}
    void ShutdownAPI() {
        for (auto it = s_callbacks.begin(); it != s_callbacks.end();) {
            it->cb(TEARDOWN_MAGIC_VALUE, it->userdata);
            it = s_callbacks.erase(it);
        }
    }
}

struct MyClient {
    struct State {
        std::string greeting;
        State(std::string g) : greeting(std::move(g)) {}

        void foo(int i) {
            std::cout
                << "State::foo with i:" << i
                << " and greeting:" << std::quoted(greeting)
                << "\n";
        }

        ~State() noexcept {
            std::cout << "~State (" << greeting << ")\n";
        }
    };
    using SharedState = std::shared_ptr<State>;
    SharedState state_;

    MyClient(std::string g) : state_(std::make_shared<State>(std::move(g))) {
        SomeAPI::register_callback(static_handler, new SharedState(state_));
    }

    ~MyClient() {
        std::cout << "~MyClient (" << state_->greeting << ")\n";
    }

    static void static_handler(int i, void* userdata) {
        auto* sharedstate = static_cast<SharedState*>(userdata);
        if (i == SomeAPI::TEARDOWN_MAGIC_VALUE) {
            delete sharedstate; // decreases refcount
            return;
        } else {
            (*sharedstate)->foo(i);
        }
    }
};

int main() {
    SomeAPI::InitAPI();

    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    SomeAPI::ShutdownAPI();
}
紧绳法 如果实际上希望将所有权传递给API,即即使
客户机
实例消失,API仍保持状态,那么根据定义,您将泄漏该状态

唯一的解决方案是,如果API有某种回调来发出它应该清理的信号。我从未见过这样的API设计,但下面是它的外观:

enum { TEARDOWN_MAGIC_VALUE = -1 };
void InitAPI() {}
void ShutdownAPI() {
    for (auto it = s_callbacks.begin(); it != s_callbacks.end();) {
        it->cb(TEARDOWN_MAGIC_VALUE, it->userdata);
        it = s_callbacks.erase(it);
    }
}
现在,我们可以将
共享\u ptr
的动态分配副本作为用户数据传递给回调(而不是指向共享指针所属副本的原始指针):

请注意,由于
SomeAPI
现在拥有共享指针的副本,因此refcount已增加。事实上,我们不必再注销回调,因为状态将保持有效,直到
SomeAPI
实际关闭:

static void static_handler(int i, void* userdata) {
    auto* sharedstate = static_cast<SharedState*>(userdata);
    if (i == SomeAPI::TEARDOWN_MAGIC_VALUE) {
        delete sharedstate; // decreases refcount
        return;
    } else {
        (*sharedstate)->foo(i);
    }
}
通过对析构函数的一些巧妙跟踪,您可以验证
状态
的生存期现在实际上由
ShutdownAPI
管理/共享:

int main() {
    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();
}
 ------- operation start
State::foo with i:1 and greeting:"Foo"
 ------- operation start
State::foo with i:2 and greeting:"Foo"
State::foo with i:3 and greeting:"Bar"
~MyClient (Bar)
 ------- operation start
State::foo with i:4 and greeting:"Foo"
State::foo with i:5 and greeting:"Bar"
~State (Bar)
~MyClient (Foo)
~State (Foo)
#include <memory>
#include <list>
#include <string>
#include <iostream>
#include <iomanip>

namespace SomeAPI {
    using Callback = void(*)(int, void* userdata);

    struct Registration {
        Callback cb;
        void* userdata;
    };
    std::list<Registration> s_callbacks;

    Registration const* register_callback(Callback cb, void* userdata) {
        s_callbacks.push_back({cb, userdata});
        return &s_callbacks.back();
    }

    size_t deregister_callback(Callback cb, void* userdata) {
        auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
        s_callbacks.remove_if([&](Registration const& r) {
            return std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
        });
        return oldsize - s_callbacks.size();
    }

    void some_operation_invoking_callbacks() {
        static int s_counter = 0;
        for (auto& reg : s_callbacks) {
            reg.cb(++s_counter, reg.userdata);
        }
    }
}

struct MyClient {
    struct State {
        std::string greeting;

        void foo(int i) {
            std::cout
                << "State::foo with i:" << i
                << " and greeting:" << std::quoted(greeting)
                << "\n";
        }
    };
    using SharedState = std::shared_ptr<State>;
    SharedState state_;

    MyClient(std::string g) : state_(std::make_shared<State>(State{g})) {
        SomeAPI::register_callback(static_handler, &state_);
    }

    ~MyClient() noexcept {
        SomeAPI::deregister_callback(static_handler, &state_);
    }

    static void static_handler(int i, void* userdata) {
        auto& state = *static_cast<SharedState*>(userdata);
        state->foo(i);
    }
};

int main() {
    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();
}
#include <memory>
#include <list>
#include <string>
#include <iostream>
#include <iomanip>

namespace SomeAPI {
    enum { TEARDOWN_MAGIC_VALUE = -1 };
    using Callback = void(*)(int, void* userdata);

    struct Registration {
        Callback cb;
        void* userdata;
    };
    std::list<Registration> s_callbacks;

    Registration const* register_callback(Callback cb, void* userdata) {
        s_callbacks.push_back({cb, userdata});
        return &s_callbacks.back();
    }

    size_t deregister_callback(Callback cb, void* userdata) {
        auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
        s_callbacks.remove_if([&](Registration const& r) {
            bool const matched = std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
            if (matched) {
                r.cb(TEARDOWN_MAGIC_VALUE, r.userdata);
            }
            return matched;
        });
        return oldsize - s_callbacks.size();
    }

    void some_operation_invoking_callbacks() {
        static int s_counter = 0;
        for (auto& reg : s_callbacks) {
            reg.cb(++s_counter, reg.userdata);
        }
    }

    void InitAPI() {}
    void ShutdownAPI() {
        for (auto it = s_callbacks.begin(); it != s_callbacks.end();) {
            it->cb(TEARDOWN_MAGIC_VALUE, it->userdata);
            it = s_callbacks.erase(it);
        }
    }
}

struct MyClient {
    struct State {
        std::string greeting;
        State(std::string g) : greeting(std::move(g)) {}

        void foo(int i) {
            std::cout
                << "State::foo with i:" << i
                << " and greeting:" << std::quoted(greeting)
                << "\n";
        }

        ~State() noexcept {
            std::cout << "~State (" << greeting << ")\n";
        }
    };
    using SharedState = std::shared_ptr<State>;
    SharedState state_;

    MyClient(std::string g) : state_(std::make_shared<State>(std::move(g))) {
        SomeAPI::register_callback(static_handler, new SharedState(state_));
    }

    ~MyClient() {
        std::cout << "~MyClient (" << state_->greeting << ")\n";
    }

    static void static_handler(int i, void* userdata) {
        auto* sharedstate = static_cast<SharedState*>(userdata);
        if (i == SomeAPI::TEARDOWN_MAGIC_VALUE) {
            delete sharedstate; // decreases refcount
            return;
        } else {
            (*sharedstate)->foo(i);
        }
    }
};

int main() {
    SomeAPI::InitAPI();

    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    SomeAPI::ShutdownAPI();
}
完整列表(经典)

int main() {
    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();
}
 ------- operation start
State::foo with i:1 and greeting:"Foo"
 ------- operation start
State::foo with i:2 and greeting:"Foo"
State::foo with i:3 and greeting:"Bar"
~MyClient (Bar)
 ------- operation start
State::foo with i:4 and greeting:"Foo"
State::foo with i:5 and greeting:"Bar"
~State (Bar)
~MyClient (Foo)
~State (Foo)
#include <memory>
#include <list>
#include <string>
#include <iostream>
#include <iomanip>

namespace SomeAPI {
    using Callback = void(*)(int, void* userdata);

    struct Registration {
        Callback cb;
        void* userdata;
    };
    std::list<Registration> s_callbacks;

    Registration const* register_callback(Callback cb, void* userdata) {
        s_callbacks.push_back({cb, userdata});
        return &s_callbacks.back();
    }

    size_t deregister_callback(Callback cb, void* userdata) {
        auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
        s_callbacks.remove_if([&](Registration const& r) {
            return std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
        });
        return oldsize - s_callbacks.size();
    }

    void some_operation_invoking_callbacks() {
        static int s_counter = 0;
        for (auto& reg : s_callbacks) {
            reg.cb(++s_counter, reg.userdata);
        }
    }
}

struct MyClient {
    struct State {
        std::string greeting;

        void foo(int i) {
            std::cout
                << "State::foo with i:" << i
                << " and greeting:" << std::quoted(greeting)
                << "\n";
        }
    };
    using SharedState = std::shared_ptr<State>;
    SharedState state_;

    MyClient(std::string g) : state_(std::make_shared<State>(State{g})) {
        SomeAPI::register_callback(static_handler, &state_);
    }

    ~MyClient() noexcept {
        SomeAPI::deregister_callback(static_handler, &state_);
    }

    static void static_handler(int i, void* userdata) {
        auto& state = *static_cast<SharedState*>(userdata);
        state->foo(i);
    }
};

int main() {
    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();
}
#include <memory>
#include <list>
#include <string>
#include <iostream>
#include <iomanip>

namespace SomeAPI {
    enum { TEARDOWN_MAGIC_VALUE = -1 };
    using Callback = void(*)(int, void* userdata);

    struct Registration {
        Callback cb;
        void* userdata;
    };
    std::list<Registration> s_callbacks;

    Registration const* register_callback(Callback cb, void* userdata) {
        s_callbacks.push_back({cb, userdata});
        return &s_callbacks.back();
    }

    size_t deregister_callback(Callback cb, void* userdata) {
        auto oldsize = s_callbacks.size(); // c++20 makes this unnecessary
        s_callbacks.remove_if([&](Registration const& r) {
            bool const matched = std::tie(r.cb, r.userdata) == std::tie(cb, userdata);
            if (matched) {
                r.cb(TEARDOWN_MAGIC_VALUE, r.userdata);
            }
            return matched;
        });
        return oldsize - s_callbacks.size();
    }

    void some_operation_invoking_callbacks() {
        static int s_counter = 0;
        for (auto& reg : s_callbacks) {
            reg.cb(++s_counter, reg.userdata);
        }
    }

    void InitAPI() {}
    void ShutdownAPI() {
        for (auto it = s_callbacks.begin(); it != s_callbacks.end();) {
            it->cb(TEARDOWN_MAGIC_VALUE, it->userdata);
            it = s_callbacks.erase(it);
        }
    }
}

struct MyClient {
    struct State {
        std::string greeting;
        State(std::string g) : greeting(std::move(g)) {}

        void foo(int i) {
            std::cout
                << "State::foo with i:" << i
                << " and greeting:" << std::quoted(greeting)
                << "\n";
        }

        ~State() noexcept {
            std::cout << "~State (" << greeting << ")\n";
        }
    };
    using SharedState = std::shared_ptr<State>;
    SharedState state_;

    MyClient(std::string g) : state_(std::make_shared<State>(std::move(g))) {
        SomeAPI::register_callback(static_handler, new SharedState(state_));
    }

    ~MyClient() {
        std::cout << "~MyClient (" << state_->greeting << ")\n";
    }

    static void static_handler(int i, void* userdata) {
        auto* sharedstate = static_cast<SharedState*>(userdata);
        if (i == SomeAPI::TEARDOWN_MAGIC_VALUE) {
            delete sharedstate; // decreases refcount
            return;
        } else {
            (*sharedstate)->foo(i);
        }
    }
};

int main() {
    SomeAPI::InitAPI();

    MyClient client1("Foo");

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    {
        MyClient client2("Bar");
        std::cout << " ------- operation start\n";
        SomeAPI::some_operation_invoking_callbacks();
    }

    std::cout << " ------- operation start\n";
    SomeAPI::some_operation_invoking_callbacks();

    SomeAPI::ShutdownAPI();
}
#包括
#包括
#包括
#包括
#包括
名称空间SomeAPI{
使用Callback=void(*)(int,void*userdata);
结构注册{
回调cb;
void*用户数据;
};
std::列出s_回调;
注册常量*注册\回调(回调cb,无效*用户数据){
s_回调。push_back({cb,userdata});
return&s_callbacks.back();
}
大小\u t取消注册\u回调(回调cb,void*userdata){
auto oldsize=s_callbacks.size();//c++20不需要这样做
s_回调。删除_if([&](注册常量&r){
返回std::tie(r.cb,r.userdata)==std::tie(cb,userdata);
});
返回oldsize-s_回调.size();
}
无效一些调用调用调用调用的操作{
静态int s_计数器=0;
用于(自动®;s\U回调){
注册cb(++s_计数器,注册用户数据);
}
}
}
结构MyClient{
结构状态{
字符串问候语;
空富(内部一){
标准::cout

当然可以。虽然param不能拥有资源,但您可以将所有权放在合适的位置谢谢@sehe-但这似乎失去了智能指针的功能。如果我在跟踪资源,为什么要使用智能指针。或者我遗漏了什么?您没有失去该功能。只是第三方库