I create my RPC Protocol with PB like:
enum EMessages {
E_MSG_METHOD_CONNECT = 0x8001,
E_MSG_EVENT_CONNECT = 0xA001,
...
}
struct MsgHeader {
required int32 sessionRef = 1;
required int32 transactionId = 2;
required int32 status = 3;
}
struct MSG_METHOD_CONNECT {
optional Messages opCode = 1 [default = E_MSG_METHOD_CONNECT];
required MsgHeader header = 2;
.. other fields ..
}
Now, I defined an interface and a template class to add a level of indirection:
class IMessage {
virtual INT getOpCode() = 0;
virtual STRING getName() = 0;
virtual size_t getSize() = 0;
virtual INT SerializeToString(STRING& out) = 0;
virtual INT ParseFromString(STRING& in) = 0;
....
}
template<class MESSAGE>
class IMessageImpl : public IMessage {
protected:
MESSAGE m_Message; ///< The Message Implementation
public:
virtual MESSAGE& getMessage() = 0;
};
And I will use it as:
IMessageImpl<MSG_METHOD_CONNECT> MsgConnect;
Now, when I receive the data from an endpoint I need, of course, to deserialize it according with the message opCode.
Reading this article I'm thinking to use a type map like boost::mpl::map but, since I never use it, I'm searching for some suggestions.
<< ------------------------ [EDIT] ------------------------ >>
Regarding the code above, I try to code it in the following way:
template<class MESSAGE>
class PBMessage : public IMessageImpl<MESSAGE>
{
public:
PBMessage() {};
/* ... other methods ... */
};
// Map of types. The key is the Message opCode
typedef typename mpl::map< mpl::pair<mpl::int_[100], PBMessage<MSG_METHOD_CONNECT> >,
mpl::pair<mpl::int_[101], PBMessage<MSG_EVENT_CONNECT> >,
> TMessageMap;
// The Message type
template < typename MessageMap, int opCode >
typedef typename mpl::at<MessageMap, mpl::int_<opCode> >::type::value TMessage;
And, to create a message from a received buffer I try to code (take it as pseudo-code):
class PBMessageFactory : public IMessageFactory {
public:
IMessage* createMessage(CHAR* buff, UINT size) {
int opCode = buff[0];
TMessage<TMessageMap, opCode> msg;
msg.ParseFromString( STRING(buff) );
}
};
But with no success...Is there someone could give me some suggestions how to retrieve types from a mpl::map?
Thanks,
Daniele.
Related
I want to create a generalized heap data structure, and facing an issue with passing template comparator.
template<typename T, typename C = less<T> > class Heap{
vector<T> *heap;
public:
Heap(vector<T> *arr){
heap = new vector<T> (arr->begin(), arr->end());
build_heap();
}
void build_heap(){
size_t n = heap->size();
for (size_t i=(n-1)/2; i>=0; i--){
shiftDown(i);
}
}
void shiftDown(size_t i){ /// heap logic
while(i < heap->size()){
size_t child = 2*i+1;
// int min_ind = 2*i+1;
if(child >= heap->size())
return;
if(child+1 < heap->size()){
if( C(heap->at(child+1),heap->at(child)) ){ // <----- using C as comparator
child++;
}
}
if( C(heap->at(child), heap->at(i)) ){ // <----- using C as comparator
swap(heap->at(child), heap->at(i));
i = child;
}
else
break;
}
}
};
int main(){
vector<int> v={8,7,6,5,4,3,2,1};
Heap<int, less<int> > heap(&v);
}
error
heap.cpp: In instantiation of ‘void Heap<T, C>::shiftDown(size_t) [with T = int; C = std::less<int>; size_t = long unsigned int]’:
heap.cpp:15:4: required from ‘void Heap<T, C>::build_heap() [with T = int; C = std::less<int>]’
heap.cpp:10:3: required from ‘Heap<T, C>::Heap(std::vector<_Tp>*) [with T = int; C = std::less<int>]’
heap.cpp:49:34: required from here
heap.cpp:32:9: error: no matching function for call to ‘std::less<int>::less(__gnu_cxx::__alloc_traits<std::allocator<int>, int>::value_type&, __gnu_cxx::__alloc_traits<std::allocator<int>, int>::value_type&)’
32 | if( C(heap->at(child+1),heap->at(child)) ){
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
detailed error
i'm following same syntex of declaration as stl c++ do, still i'm getting error. please help me out.
template<typename T, typename C = less<T> > class Heap;
any help or pointer to help is appreciated. thank you.
template<class T>
class Comparator{
bool operator()(const T &a, const T &b){
...
// returns logic
}
}
template<class T, class Comp >
class AnyClass{
public:
...
void function(){
// code ...
Comp<T>()(obj1, obj2);
}
...
}
calling sytex :
...
AnyClass *obj = new AnyClass<Type , Comparator>();
obj.function()
...
passing Comparator to templated class and when we need to compare objects
we create a functional object and call operator() with args to compare.
In question, that object is less<int>.
Comp<T>()(obj1, obj2);
Historically, I've been using trait classes to hold information and apply that into a "generic" function that runs the same "algorithm." Only differed by the trait class. For example: https://onlinegdb.com/ryUo7WRmN
enum selector { SELECTOR1, SELECTOR2, SELECTOR3, };
// declaration
template < selector T> struct example_trait;
template<> struct example_trait<SELECTOR1> {
static constexpr size_t member_var = 3;
static size_t do_something() { return 0; }
};
template<> struct example_trait<SELECTOR2> {
static constexpr size_t member_var = 5;
static size_t do_something() { return 0; }
};
// pretend this is doing something useful but common
template < selector T, typename TT = example_trait<T> >
void function() {
std::cout << TT::member_var << std::endl;
std::cout << TT::do_something() << std::endl;
}
int main()
{
function<SELECTOR1>();
function<SELECTOR2>();
return 0;
}
I'm not sure how to create "generic" algorithms this when dealing with polymorphic classes.
For example: https://onlinegdb.com/S1hFLGC7V
Below I have created an inherited class hierarchy. In this example I have a base catch-all example that defaults all the parameters to something (0 in this case). And then each derived class sets overrides specific methods.
#include <iostream>
#include <memory>
#include <type_traits>
#include <assert.h>
using namespace std;
struct Base {
virtual int get_thing_one() {
return 0;
}
virtual int get_thing_two() {
return 0;
}
virtual int get_thing_three() {
return 0;
}
virtual int get_thing_four() {
return 0;
}
};
struct A : public Base {
virtual int get_thing_one() override {
return 1;
}
virtual int get_thing_three() override {
return 3;
}
};
struct B : public Base {
virtual int get_thing_one() override {
return 2;
}
virtual int get_thing_four() override{
return 4;
}
};
Here I created a simple factory, not elegant but for illustrative purposes
// example simple factory
std::shared_ptr<Base> get_class(const int input) {
switch(input)
{
case 0:
return std::shared_ptr<Base>(std::make_shared<A>());
break;
case 1:
return std::shared_ptr<Base>(std::make_shared<B>());
break;
default:
assert(false);
break;
}
}
So this is the class of interest. It is a class does "something" with the data from the classes above. The methods below are a simple addition example but imagine a more complicated algorithm that is very similar for every method.
// class that uses the shared_ptr
class setter {
private:
std::shared_ptr<Base> l_ptr;
public:
setter(const std::shared_ptr<Base>& input):l_ptr(input)
{}
int get_thing_a()
{
return l_ptr->get_thing_one() + l_ptr->get_thing_two();
}
int get_thing_b()
{
return l_ptr->get_thing_three() + l_ptr->get_thing_four();
}
};
int main()
{
constexpr int select = 0;
std::shared_ptr<Base> example = get_class(select);
setter l_setter(example);
std::cout << l_setter.get_thing_a() << std::endl;
std::cout << l_setter.get_thing_b() << std::endl;
return 0;
}
How can I make the "boilerplate" inside the setter class more generic? I can't use traits as I did in the example above because I can't tie static functions with an object. So is there a way to make the boilerplate example more common?
Somewhere along the lines of having a selector, say
enum thing_select { THINGA, THINGB, };
template < thing_select T >
struct thing_traits;
template <>
struct thing_traits<THINGA>
{
static int first_function() --> somehow tied to shared_ptr<Base> 'thing_one' method
static int second_function() --> somehow tied to shared_ptr<Base> 'thing_two' method
}
template <>
struct thing_traits<THINGB>
{
static int first_function() --> somehow tied to shared_ptr<Base> 'thing_three' method
static int second_function() --> somehow tied to shared_ptr<Base> 'thing_four' method
}
// generic function I'd like to create
template < thing_select T, typename TT = thing_traits<T> >
int perform_action(...)
{
return TT::first_function(..) + TT::second_function(..);
}
I ideally would like to modify the class above to something along the lines of
// Inside setter class further above
int get_thing_a()
{
return perform_action<THINGA>(...);
}
int get_thing_b()
{
return perform_action<THINGB>(...);
}
The answer is, maybe I can't, and I need to pass int the shared_ptr as a parameter and call the specific methods I need instead of trying to tie a shared_ptr method to a static function (in hindsight, that doesn't sound like a good idea...but I wanted to bounce my idea)
Whoever makes the actual call will need a reference of the object, one way or the other. Therefore, assuming you want perform_action to perform the actual call, you will have to pass the parameter.
Now, if you really want to store which function of Base to call as a static in thing_traits without passing a parameter, you can leverage pointer to member functions:
template <>
struct thing_traits<THINGA>
{
static constexpr int (Base::*first_function)() = &Base::get_thing_one;
...
}
template < thing_select T, typename TT = thing_traits<T>>
int perform_action(Base & b)
{
return (b.*TT::first_function)() + ...;
}
You can also play instead with returning a function object that does the call for you (and the inner function takes the parameter).
It all depends on who you need to make the call and what information/dependencies you assume you have available in each class/template.
I would like to make a new message type called wsm_info.
In this message type, I want to include a vehicle structure, as it follows:
struct vehicle{
int vehicle_id;
Coord vehicle_pos;
float speed;
};
In the veins example there is a function called: prepareWSM that's declared in BaseWaveApplLayer.h. This function is a virtual WaveShortMessage* type.
If the wsm_info was inherented from WaveShortMessage I wouldn't need to write and declare a new prepareWSM for wsm_info, right?
So how can I make this wsm_info message inherented of WaveShortMessage?
I tried to write like this in the wsm_info.h:
class wsm_info : public WaveShortMessage
Instead of, that was written previously:
class wsm_info : public ::omnetpp::cPacket
But the error that I get is the following one:
cannot initialize a variable of type wsm_info * with an rvalue of type WaveShortMessage
The full code of my msg_info is below:
cplusplus {{
#include "veins/base/utils/Coord.h"
#include "veins/modules/messages/WaveShortMessage_m.h"
}}
class noncobject Coord;
class WaveShortMessage;
struct vehicle {
int vehicle_id;
Coord vehicle_pos;
float speed;
};
message wsm_info extends WaveShortMessage {
//Version of the Wave Short Message
int wsmVersion = 0;
//Determine which security mechanism was used
int securityType = 0;
//Channel Number on which this packet was sent
int channelNumber;
//Data rate with which this packet was sent
int dataRate = 1;
//Power Level with which this packet was sent
int priority = 3;
//Unique number to identify the service
int psid = 0;
//Provider Service Context
string psc = "Service with some Data";
//Length of Wave Short Message
int wsmLength;
vehicle data;
int senderAddress = 0;
int recipientAddress = -1;
int serial = 0;
Coord senderPos;
simtime_t timestamp = 0;
}
Can anyone take a look on my code and point me where is wrong and why? Thanks!
The msg_info.msg should have the following content:
cplusplus {{
#include "veins/modules/messages/WaveShortMessage_m.h"
}}
class noncobject Coord;
struct vehicle {
int vehicle_id;
Coord vehicle_pos;
float speed;
};
class WaveShortMessage;
packet wsm_info extends WaveShortMessage {
vehicle data;
}
You cannot use prepareWSM() because it creates a WaveShortMessage object which cannot be cast to wsm_info. Instead you may write a new method, for example:
In /veins/src/veins/modules/application/ieee80211p/BaseWaveApplLayer.h add:
#include "veins/modules/messages/wsm_info_m.h"
and in the class add the declaration:
wsm_info* prepare_wsm_info(std::string name, int dataLengthBits, t_channel channel, int priority, int rcvId, int serial=0);
In /veins/src/veins/modules/application/ieee80211p/BaseWaveApplLayer.cc add:
wsm_info* BaseWaveApplLayer::prepare_wsm_info(std::string name, int lengthBits, t_channel channel, int priority, int rcvId, int serial) {
wsm_info* wsm = new wsm_info(name.c_str());
// ... content similar to prepareWSM()
}
In order to set vehicle structure you can just write:
wsm_info* info = prepare_wsm_info(/* parameters */);
vehicle veh;
veh.speed = 60;
veh.vehicle_id = 3;
// ...
info->setData(veh);
Alternatively you can add parameters for vehicle in the definition of prepare_wsm_info().
If i get you right, you want to extend your wsm_info.msg, is that correct?
According to THIS question, you can modify your wsm_info.msg in the following way:
cplusplus {{
#include "veins/modules/messages/WaveShortMessage_m.h"
}}
class WaveShortMessage;
message wsm_info extends WaveShortMessage {
int vehicle_id;
Coord vehicle_pos;
float speed;
}
where must be declare wsm_info.msg ?in which folder?
i have want to make template class Vector , parameters should be Type and length of an dynamic array thats in it.
template < class Type, int length >
class Vektor
{
public:
int Count;
int CurrentPos;
Type* Beginning = new Type[count];
int LastAtUse=0;
Vektor()
{
Count = length;
}
void PushBack(Type A)
{
Beginning[LastAtUse]=A;
LastAtUse++;
}
void insert(Type A, int position)
{
Beginning[position] = A;
}
};
I tried to test it in main and am getting an error:
error C2440: 'initializing' : cannot convert from 'iterator_traits<_Iter>::difference_type (__cdecl *)(_InIt,_InIt,const _Ty &)' to 'unsigned int'
Can you help me find what I'm doing wrong ?
Here:
Type* Beginning = new Type[count];
^
you have Count, not count
also, Count is not yet set when your new executes, you should move it to constructor here:
Vektor()
{
Count = length;
Beginning = new Type[Count];
}
I have:
struct employee
{
uint64_t id;
uint32_t a;
uint32_t b;
employee() { }
struct By_id {};
struct By_a {};
struct By_b {};
struct Change_a : public std::unary_function< employee, void >
{
uint32_t p;
Change_a(const uint32_t &_p) : p(_p) {}
void operator()(employee & r) { r.a = p; }
};
struct Change_b : public std::unary_function< employee, void >
{
uint32_t p;
Change_a(const uint32_t &_p) : p(_p) {}
void operator()(employee & r) { r.b = p; }
};
};
typedef multi_index_container<
employee,
indexed_by<
ordered_unique< tag<employee::By_id>, member<employee, uint64_t, &employee::id> >,
ordered_non_unique< tag<employee::By_a>, member<employee, uint32_t, &employee::a> >,
ordered_non_unique< tag<employee::By_b>, member<employee, uint32_t, &employee::b> >,
>
> employee_set;
employee_set es;
typedef employee_set::index<employee::By_id>::type List_id;
typedef employee_set::index<employee::By_a>::type List_a;
typedef employee_set::index<employee::By_b>::type List_b;
//...
thread 1
List_id::iterator it_id;
es.modify( it_id, employee::Change_a( 0 ) );
thread 2
List_id::iterator it_id;
es.modify( it_id, employee::Change_b( 0 ) );
//...
This standart example how to work with boost multi index container.
if find some node by id and store iterator in List_id::iterator it_id;
I want to change (modify) different fields of employee in different threads.
Does the concurent operations are thread safe?
Boost.MultiIndex has the same very basic thread safety guarantees than other containers in the standard library:
Concurrent read-only access is OK.
Concurrent write access must be externally synchronized by the user (you).
So, calls to modify (or any other operation resulting in changes in the container) must be guarded with some mutex-like mechanism.