gpt4 book ai didi

c++ - 如何在 C++ 中模拟模板化的 std::function

转载 作者:太空宇宙 更新时间:2023-11-04 13:01:24 24 4
gpt4 key购买 nike

以下是我在 C++ 程序中所做的基本实例。我有一个监听器列表,它们都是 std::function。我有一个概念DataType,意思是监听者对什么样的数据感兴趣。这里的思路和发布-订阅模式是一样的。对某种数据感兴趣的方法应该能够使用 AddListener 将自己添加到监听器列表中。添加了一些方法,它们会在需要时收到回调。

程序运行良好!!

#include <iostream>
#include <functional>
#include <vector>
#include <string>

enum class DataType {
Type_1,
Type_2
// and so on
};

typedef std::function<void(std::pair<DataType, std::string>)> MyListenerType;

//template <typename T>
//typedef std::function<void(T>)> MyListenerType;
// How can I emulate the above so that a method passing any kind of primitive data-type namely "int, bool, float or double" can be added into
// my vector of listners.


std::vector<MyListenerType> my_data_listeners_1;
std::vector<MyListenerType> my_data_listeners_2;

void ListenerMethod_Instance_1(std::pair<DataType, std::string> information) {

DataType data_type = information.first;
std::string message = information.second;
std::cout << "ListenerMethod_Instance_1 called with message " << message << "\n";
}

void ListenerMethod_Instance_2(std::pair<DataType, std::string> information) {

DataType data_type = information.first;
std::string message = information.second;
std::cout << "ListenerMethod_Instance_2 called with message " << message << "\n";
}

void AddListener (MyListenerType listener, DataType type_of_interest) {

if (DataType::Type_1 == type_of_interest) {
my_data_listeners_1.push_back(listener);
std::cout << "Added a method instance for DataType::Type_1" << "\n";
}
else if (DataType::Type_2 == type_of_interest) {
my_data_listeners_2.push_back(listener);
std::cout << "Added a method instance for DataType::Type_2" << "\n";
}
else {
std::cout << "Listener type not supported" << "\n";
}
}

void CallAllListnersWhohaveSuscribed() {

if (!my_data_listeners_1.empty()) {
std::string send_message_1 = "some message 123";
std::pair <DataType, std::string> info_to_send_1 = std::make_pair (DataType::Type_1, send_message_1);
for(auto const &listener : my_data_listeners_1) {
listener(info_to_send_1);
}
}

if (!my_data_listeners_2.empty()) {
std::string send_message_2 = "some message 456";
std::pair <DataType, std::string> info_to_send_2 = std::make_pair (DataType::Type_2, send_message_2);
for(auto const &listener : my_data_listeners_2) {
listener(info_to_send_2);
}
}
}

int main() {

// Add ListenerMethod_Instance_1 for instance
DataType data_type_1 = DataType::Type_1;
auto listener_instance_1 = std::bind(ListenerMethod_Instance_1, std::placeholders::_1);
AddListener(listener_instance_1, data_type_1);

// Add ListenerMethod_Instance_2 for instance
DataType data_type_2 = DataType::Type_2;
auto listener_instance_2 = std::bind(ListenerMethod_Instance_2, std::placeholders::_1);
AddListener(listener_instance_2, data_type_2);

CallAllListnersWhohaveSuscribed();
return 0;
}

程序输出如下:

./stdFunctionTest
Added a method instance for DataType::Type_1
Added a method instance for DataType::Type_2
ListenerMethod_Instance_1 called with message some message 123
ListenerMethod_Instance_2 called with message some message 456

但这是我想要修改和挣扎的方式。 需要注意的是,每个 ListenerMethod_Instance_1ListenerMethod_Instance_2 都必须解析这对获取我不想获取的信息。我想启用任何 C++ 原始数据类型的方法,无论是“int、bool、float 还是 double”,以便能够添加到监听器 vector 中并接收回调。例如,以下方法应该“可添加”到 AddListener 中。

void ListenerMethod_Instance_3(int integer_data) {

std::cout << "ListenerMethod_Instance_3 called with integer_data " << integer_data << "\n";
}

看看这个 link here 看起来有点可能。但我正在努力使它适应我这里的用例。请提出建议。

那么,基本上我如何使用 std::function 实现模板功能?

最佳答案

struct anything_view_t {
void* ptr=0;
template<class T, std::enable_if_t<!std::is_same<anything_view_t, std::decay_t<T>>{}, int> =0>
anything_view_t(T&&t):ptr(std::addressof(t)){}
anything_view_t()=default;
anything_view_t(anything_view_t const&)=default;
anything_view_t& operator=(anything_view_t const&)=default;
template<class T>
operator T() const { return *static_cast<T*>(ptr); }
};

这是一种非常不安全的类型删除 View 。

struct any_callbacks {
std::unordered_map<std::type_index, std::vector<std::function<void(anything_view_t)>>> table;
template<class T>
void add_callback( std::function<void(T)> f ){
table[typeid(T)].push_back(f);
}
template<class T>
void invoke_callbacks(T t) const {
auto it = table.find(typeid(T));
if (it==table.end()) return;
for(auto&&f:it->second)
f(t);
}
};

类似上面的东西应该可以工作。 T 类型必须完全匹配。不支持引用。代码未编译,设计合理,可能有拼写错误。

这不是重构为原始类型。您应该显式传递 T,不要依赖演绎,因为它很脆弱。

关于c++ - 如何在 C++ 中模拟模板化的 std::function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44114713/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com