gpt4 book ai didi

c++ - cpp中如何根据数据类型将数据推送到不同的队列?

转载 作者:行者123 更新时间:2023-12-05 05:43:34 26 4
gpt4 key购买 nike

我在根据数据类型将数据推送到不同队列时遇到问题。

具体来说,我有多个请求类。例如:

class RequestA {
};
class RequestB {
};
class RequestC {
};
...

这些请求可能会被某些类继承(例如,class Request)。

这些数据类型的每个对象必须放入不同的队列中。例如:

std::vector<RequestA> queueA;
std::vector<RequestB> queueB;
std::vector<RequestC> queueC;
...

我需要为每个类使用不同队列的原因是,队列顶部(前面) 的每个请求都需要不同的(后)处理步骤后面

例如,

class RequestHandler {
public:
void tick() {
// Multiple requests might be accumulated in the queue before calling tick()
if (!queueA.empty()) {
processA(queueA.front())
queueA.pop_front(); // assume std::vector has pop_front()
}
// queueB can be empty although other queues are full of elements
if (!queueB.empty()) {
...
}
...
// Polymorphism might be used.
// if RequestA, RequestB, ... are derived by Request:
if (!poly_queue.empty()) {
Request* req = poly_queue.top();
req->process(/* status of handler */);
poly_queue.pop_front(); // assume std::vector has pop_front()
// However, the result is not same as one using separated queue,
// because the order of requests is not preserved.
// For example, in the separated queue example, the processing order might be,
// RequestA -> Request C or only RequestA.
// However, if I use the single queue, we cannot achieve same result.

}
private:
std::vector<RequestA> queueA;
std::vector<RequestB> queueB;
std::vector<RequestC> queueC;
...
std::vector<Request*> poly_queue;
};

但是,问题是,要将数据推送到队列中,我可能会使用以下方法:

if (typeid()) {
queueA.push_back();
} else if (typeid()) {
queueB.push_back();
} ...

或者如果 RequestA, RequestB, ... 被 Request 类继承:

std::map<std::type_index, std::vector<Request*>> queue;

queue[typeid()].push_back(...);

可能会用到。

但是,最好避免使用 typeiddynamic_cast

如何有效处理这种情况?

最佳答案

一种可能的方法是使用模板和 std::map .特别是,您可以创建一个名为 addRequest成员函数模板对于 RequestHandler类来处理不同的请求。

方法一

第一步

创建一个 std::map .

std::map<std::type_index, void*> myMap{{typeid(RequestA), &queueA}, 
{typeid(RequestB), &queueB},
{typeid(RequestC), &queueC}};

第二步

为成员函数模板添加声明add<>内部类RequestHandler .

template<typename T> void addRequest(T Arg);

第三步

实现 addRequest成员函数模板。

template<typename T> void RequestHandler::addRequest(T Arg) // - STEP 3
{


(*static_cast<std::vector<decltype(Arg)>*>(myMap.at(typeid(Arg)))).push_back(Arg);

}

工作示例

#include <iostream>
#include <map>
#include <vector>
#include <typeindex>


struct RequestA{};
struct RequestB{};
struct RequestC{};


class RequestHandler {
public:
void tick()
{
std::cout<<"tick called"<<std::endl;
}
private:
std::vector<RequestA> queueA;
std::vector<RequestB> queueB;
std::vector<RequestC> queueC;

//create std::map - STEP 1
std::map<std::type_index, void*> myMap{{typeid(RequestA), &queueA},
{typeid(RequestB), &queueB},
{typeid(RequestC), &queueC}};
public:
//create member function template - STEP 2
template<typename T> void addRequest(T Arg);

};
template<typename T> void RequestHandler::addRequest(T Arg) // - STEP 3
{
std::cout << "add called on " <<typeid(Arg).name() << std::endl;//just for debugging purposes
std::cout << "size before push_back "<< (*static_cast<std::vector<decltype(Arg)>*>(myMap.at(typeid(Arg)))).size()<<std::endl;//just for debugging
(*static_cast<std::vector<decltype(Arg)>*>(myMap.at(typeid(Arg)))).push_back(Arg);
std::cout << "size after push_back "<< (*static_cast<std::vector<decltype(Arg)>*>(myMap.at(typeid(Arg)))).size()<<std::endl;

std::cout<<"--------------------------------------"<<std::endl;
}


int main()
{

RequestA A;
RequestB B;
RequestC C;

RequestHandler rq;

//call RequestHandler's add method simulating the requests
rq.addRequest(A);

rq.addRequest(B);
rq.addRequest(B);

rq.addRequest(C);

}

Working demo


方法二

对于 C++17,我们可以使用 std::any而不是 void* .基本步骤与之前的方法相同。

#include <iostream>
#include <map>
#include <vector>
#include <typeindex>
#include <any>
#include <functional>
struct RequestA{};
struct RequestB{};
struct RequestC{};


class RequestHandler {
public:
void tick()
{
std::cout<<"tick called"<<std::endl;
}
private:
std::vector<RequestA> queueA;
std::vector<RequestB> queueB;
std::vector<RequestC> queueC;

//create std::map - STEP 1
std::map<std::type_index, std::any> myMap{{typeid(RequestA), std::ref(queueA)},
{typeid(RequestB), std::ref(queueB)},
{typeid(RequestC), std::ref(queueC)}};
public:
//create member function template - STEP 2
template<typename T> void addRequest(T Arg);

};
template<typename T> void RequestHandler::addRequest(T Arg) // - STEP 3
{
std::cout << "add called on " <<typeid(Arg).name() << std::endl;//just for debugging purposes
std::cout << "size before push_back "<< std::any_cast<std::reference_wrapper<std::vector<T>>>(myMap.at(typeid(T))).get().size()<<std::endl;//just for debugging

std::any_cast<std::reference_wrapper<std::vector<T>>>(myMap.at(typeid(T))).get().push_back(Arg);
std::cout << "size after push_back "<< std::any_cast<std::reference_wrapper<std::vector<T>>>(myMap.at(typeid(T))).get().size()<<std::endl;

std::cout<<"--------------------------------------"<<std::endl;
}


int main()
{

RequestA A;
RequestB B;
RequestC C;

RequestHandler rq;

//call RequestHandler's add method simulating the requests
rq.addRequest(A);

rq.addRequest(B);
rq.addRequest(B);

rq.addRequest(C);

}

Working demo

以上只是根据我目前对您的需求的了解进行的演示。我花了一段时间(大约 40 分钟)来理解需求并相应地编写代码。我在理解您的要求方面可能仍然是错误的。所以让我知道这是否是您想要的。您也可以根据需要修改代码。

关于c++ - cpp中如何根据数据类型将数据推送到不同的队列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71800804/

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