C++ Event Handling - issue with const - c++

I already asked about my Problem, now I'm on the next Step. In the code below I have the Problem, that I always have to make the EventHandler (Server::HandleMessage) static. But I need to have it non static to access other Variables in the Server class from within the Handler.
How can I achieve this?
Here my Code:
#include <iostream>
#include <functional>
using namespace std;
class Client{
public:
struct MessageReceiveArgs {
MessageReceiveArgs(int ID, const std::string& Text) : ID(ID), Text(Text) {}
int ID;
std::string Text;
};
std::function<void(MessageReceiveArgs)> onMessageReceive;
Client(){}
void FireEvent(){
this->onMessageReceive(MessageReceiveArgs(16, "SomeText"));
}
};
class Server{
public:
int i;
Server(){
this->client.onMessageReceive = &Server::HandleMessage;
this->i = 5;
}
void FireEvent(){
this->client.FireEvent();
}
Client client;
static void HandleMessage(Client::MessageReceiveArgs args) {
std::cout<<"ID "<<args.ID<<": "<<" "<<args.Text<<std::endl;
//need it non static
//std::cout<<"I: "<<this->i<<std::endl;
}
};
int main() {
Server sv = Server();
sv.FireEvent();
}
As mentioned in my earlier Post, i'm new to Standard C++ (Unix).

I'm fairly sure this is what you're after. You need to bind the implicit this explicitly when invoking a pointer-to-member through std::function in the fashion you seem to desire.
#include <iostream>
#include <functional>
using namespace std;
class Client{
public:
struct MessageReceiveArgs
{
MessageReceiveArgs(int ID, const std::string& Text)
: ID(ID), Text(Text) {}
int ID;
std::string Text;
};
Client(){}
void FireEvent()
{
this->onMessageReceive(MessageReceiveArgs(16, "SomeText"));
}
std::function<void(MessageReceiveArgs)> onMessageReceive;
};
class Server
{
public:
int i;
Server()
{
this->client.onMessageReceive
= std::bind(&Server::HandleMessage, this, std::placeholders::_1);
this->i = 5;
}
void FireEvent()
{
this->client.FireEvent();
}
Client client;
void HandleMessage(Client::MessageReceiveArgs args)
{
std::cout<<"ID "<<args.ID<<": "<<" "<<args.Text<<std::endl;
}
};
int main()
{
Server sv = Server();
sv.FireEvent();
}
Output
ID 16: SomeText

Related

How to pass smart pointer instead of "this" in C++ 11?

I am using c++11 compiler.
I have two classes - class Test and class TestHelper.
The class Test is a friend-to-class TestHelper.
The class Test is only which we can access from outside.
Now, we want to call Test API i.e. setVal(). This setVal() should call
Test2 API i.e. setX and is expecting this pointer. I don't want to use this pointer but want
to use a smart pointer instead. How can I do so?
The notion of this kind of desirability is because of the fact that in reality, my class Test is pretty big. So, I am trying to make a helper class for Test i.e.
class TestHelper;
class Test
{
friend class TestHelper;
int x;
public:
void display() {
std::cout << x;
}
void setVal(int val) {
TestHelper testH;
testH.setX(this, 324);
}
};
class TestHelper
{
public:
void setX(Test *test, int val) {
/** some algorithm here and then change val to something else */
test->x = val*100;
}
};
int main()
{
std::cout << "Hello World!\n";
Test x;
x.setVal(130);
}
I tried changing the prototype from void setX(Test *test, int val)
to void setX(std::shared_ptr<Test> test, int val) but don't know how to pass this pointer
as std::shared_ptr<Test> test here.
So here is working solution with shared pointers. The example doesn't even compile due to missing definitions so you have to restructure your code into headers and cpp files.
Test.h:
#ifndef TEST_H
#define TEST_H
#include <memory>
#include "TestHelper.h"
class Test : public std::enable_shared_from_this<Test>
{
private:
friend class TestHelper;
int x;
public:
void display();
void setVal(int val);
};
#endif
Test.cpp:
#include <iostream>
#include "Test.h"
void Test::display() {
std::cout << x;
}
void Test::setVal(int val) {
TestHelper testH;
testH.setX(shared_from_this(), 324);
}
TestHelper.h:
#ifndef TESTHELPER_H
#define TESTHELPER_H
class Test;
class TestHelper
{
public:
void setX(std::shared_ptr<Test> test, int val);
};
#endif
TestHelper.cpp:
#include <memory>
#include "TestHelper.h"
#include "Test.h"
void TestHelper::setX(std::shared_ptr<Test> test, int val) {
/** some algorithm here and then change val to something else */
test->x = val*100;
}
main.cpp:
#include <iostream>
#include <memory>
#include "Test.h"
int main(void){
std::cout << "Hello World!\n";
auto x = std::make_shared<Test>();
x->setVal(130);
x->display();
}
You can run it here: https://paiza.io/projects/e/79dehCx0RRAG4so-sVZcQw
I don't understand why you want this, here's a few variants that compile
reference
// Reference variant
#include <iostream>
class Test;
class TestHelper
{
public:
void setX(Test & test, int val);
};
class Test
{
friend class TestHelper;
int x;
public:
void display() {
std::cout << x;
}
void setVal(int val) {
TestHelper testH;
testH.setX(*this, 324);
}
};
void TestHelper::setX(Test &test, int val)
{
/** some algorithm here and then change val to something else */
test.x = val*100;
}
int main()
{
Test x;
x.setVal(130);
x.display();
}
http://cpp.sh/7t3ec
shared ptr
// Shared ptr variant
#include <iostream>
#include <memory> // Required for shared_ptrs
class Test;
class TestHelper
{
public:
void setX(std::shared_ptr<Test> test, int val);
};
class Test : public std::enable_shared_from_this<Test>
{
friend class TestHelper;
int x;
public:
void display() {
std::cout << x;
}
void setVal(int val) {
TestHelper testH;
testH.setX(shared_from_this(), 324);
}
};
void TestHelper::setX(std::shared_ptr<Test> test, int val)
{
/** some algorithm here and then change val to something else */
test->x = val*100;
}
int main()
{
auto x = std::make_shared<Test>(); // x needs to be created as shared_ptr or it won't work
x->setVal(130);
x->display();
}
http://cpp.sh/87ao2
Perhaps with these you can refine your question?

How to initialize shared pointers in constructor?

I am trying to initialize objects from other classes in my constructor as shared pointers. I need a shred pointer because I need a reference to use in another method in ...
header
class MyClass
{
public:
MyClass() ;
~MyClass() {};
void myMethod();
private:
std::shared_ptr<dds::pub::Publisher>m_pub;
std::shared_ptr<dds::domain::DomainParticipant>m_part;
};
cpp
MyClass::MyClass()
{
m_part = std::make_shared<dds::domain::DomainParticipant>(domain::default_id());
m_pub = std::make_shared<dds::pub::Publisher>(m_part);
}
MyClass::myMethod()
{
//m_part, m_pub are used here
}
what am I missing here?
Error C2039 'delegate': is not a member of 'std::shared_ptr<dds::domain::DomainParticipant>'
dds::pub::Publisher
namespace dds
{
namespace pub
{
typedef dds::pub::detail::Publisher Publisher;
}
}
Publisher
namespace dds { namespace pub { namespace detail {
typedef
dds::pub::TPublisher<org::eclipse::cyclonedds::pub::PublisherDelegate> Publisher;
} } }
PublisherDelegate
namespace dds { namespace pub { namespace detail {
typedef
dds::pub::TPublisher<org::eclipse::cyclonedds::pub::PublisherDelegate> Publisher;
} } }
class OMG_DDS_API PublisherDelegate : public
org::eclipse::cyclonedds::core::EntityDelegate
{
public:
typedef ::dds::core::smart_ptr_traits< PublisherDelegate >::ref_type ref_type;
typedef ::dds::core::smart_ptr_traits< PublisherDelegate >::weak_ref_type weak_ref_type;
PublisherDelegate(const dds::domain::DomainParticipant& dp,
const dds::pub::qos::PublisherQos& qos,
dds::pub::PublisherListener* listener,
const dds::core::status::StatusMask& event_mask);
TPublisher
template <typename DELEGATE>
class dds::pub::TPublisher : public dds::core::TEntity<DELEGATE>
{
public:
typedef dds::pub::PublisherListener Listener;
public:
OMG_DDS_REF_TYPE_PROTECTED_DC(TPublisher, dds::core::TEntity, DELEGATE)
OMG_DDS_IMPLICIT_REF_BASE(TPublisher)
TPublisher(const dds::domain::DomainParticipant& dp);
TPublisher(const dds::domain::DomainParticipant& dp,
const dds::pub::qos::PublisherQos& qos,
dds::pub::PublisherListener* listener = NULL,
const dds::core::status::StatusMask& mask = dds::core::status::StatusMask::none());
I tried the method given in answer got new error,
Error C2672 'std::dynamic_pointer_cast': no matching overloaded function in TPublisher.hpp
I guess m_pub should be initialised like this
m_pub = std::make_shared<dds::pub::Publisher>(*m_part);
The class dds::pub::Publisher a.k.a. dds::pub::TPublisher has the constructor taking const dds::domain::DomainParticipant by reference.
The answer is changed after the question has been updated.

C++ How to place data in vector of base class

Here is my base class:
#include <string>
#include "DataStruct.h"
#include <vector>
#include <mysqlx/xdevapi.h>
#include <iostream>
#include <memory>
namespace Vibranium {
using namespace mysqlx;
class MySQLTable {
public:
MySQLTable();
virtual ~MySQLTable() = default;
int Index;
std::string tableName;
DataStruct dataStruct;
std::vector<std::unique_ptr<DataStruct>> Data;
Table getTable(Session& conn) const;
RowResult getAll(Session& conn) const;
virtual void LoadTable(RowResult& res) {}
};
}
#endif //VIBRANIUM_CORE_MYSQLTABLE_H
Which is representing all MySQL tables i might have. Take a look at Data vector of types DataStruct. I use DataStruct as a base struct because all tables will have different structure.
Here is base DataStruct struct:
namespace Vibranium{
struct DataStruct{};
}
Than I define my first mysql tablle Accounts:
#include <string>
#include "Database/DataStruct.h"
#include "Database/MySQLTable.h"
namespace Vibranium{
using namespace std;
struct AccountsStruct : DataStruct{
int id;
std::string email;
std::string warTag;
int state;
std::string name;
std::string lastname;
std::string country;
int dob_month;
int dob_day;
int dob_year;
double balance;
std::string created_at;
std::string updated_at;
int account_role;
int rank;
int playerRole;
};
class Accounts : public MySQLTable{
public:
Accounts() = default;
void LoadTable(RowResult& res) override;
};
}
As you can see inside I have defined AccountsStruct as child of DataStruct.
Here is how I implement LoadTable:
#include "Accounts.h"
using namespace Vibranium;
void Vibranium::Accounts::LoadTable(RowResult &res) {
std::vector<AccountsStruct> accounts;
AccountsStruct accountsStruct;
for (Row row : res.fetchAll()){
accountsStruct.id = row[0].get<int>();
accountsStruct.email = row[1].get<std::string>();
accountsStruct.warTag = row[2].get<std::string>();
accountsStruct.state = row[4].get<int>();
accountsStruct.name = row[5].get<std::string>();
accountsStruct.lastname = row[6].get<std::string>();
accountsStruct.country = row[7].get<std::string>();
accountsStruct.dob_month = row[8].get<int>();
accountsStruct.dob_day = row[9].get<int>();
accountsStruct.dob_year = row[10].get<int>();
accountsStruct.balance = row[11].get<double>();
accountsStruct.created_at = row[12].get<std::string>();
accountsStruct.updated_at = row[13].get<std::string>();
accountsStruct.account_role = row[15].get<int>();
accountsStruct.rank = row[16].get<int>();
accountsStruct.playerRole = row[17].get<int>();
accounts.push_back(accountsStruct);
}
}
As Accounts is child of MySQLTable
I would like to add all the data from std::vector<AccountsStruct> accounts into Data vector inherited from MySQlTable.
Also after that I would like to cycle thru the vector Data as it
is of type Accounts instead of MySQLTable class. However I don't
know how can I achieve those two things.
Is it possible and how?
I would drop the type DataStruct, and make MySqlTable a template.
#include <string>
#include <vector>
#include <mysqlx/xdevapi.h>
#include <memory>
namespace Vibranium {
using mysqlx::Table;
using mysqlx::RowResult;
using mysqlx::Session;
class MySQLTableBase {
public:
MySQLTableBase();
virtual ~MySQLTableBase() = default;
Table getTable(Session& conn) const;
RowResult getAll(Session& conn) const;
int Index;
std::string tableName;
};
template <typename T>
class MySQLTable : public MySQLTableBase {
public:
virtual void LoadTable(RowResult& res) = 0;
T dataStruct; // What is this?
std::vector<T> Data; // You don't need vector of pointers
};
}
Then you define Account and Accounts as
#include <string>
#include "Database/MySQLTable.h"
namespace Vibranium{
struct Account{
int id;
std::string email;
std::string warTag;
int state;
std::string name;
std::string lastname;
std::string country;
int dob_month;
int dob_day;
int dob_year;
double balance;
std::string created_at;
std::string updated_at;
int account_role;
int rank;
int playerRole;
};
class Accounts : public MySQLTable<Account>{
public:
Accounts() = default;
void LoadTable(RowResult& res) override;
};
}
So, have fun with C++!
You don't have a vector in MySQLTable with name "Data". You have method (Data) returning vector of ... To implement your request you should create method (for example) void SetData(...).
You can't. You can cycle through vector of Data and cast (for example static_cast, or other) each element from Data to AccountStruct. WARNING! Wrong cast operation may cause undefined behavior, crashes, etc.!

error: base operand of '->' has non-pointer type

This is my enum header file
//use like PostionType::President
enum PositionType
{ President,
VicePresident,
Secretary,
Treasurer,
Normal
};
And in my Ballot paper header and cpp file
#include <list>
#include <iostream>
#include "Candidate.h"
#include "PositionType.h" //include enum
class BallotPaper
{
private:
PositionType _positionbp;
std::list<Candidate> _candidatesbp;
public:
BallotPaper();
void setPositionBP(PositionType positionbp);
PositionType getPositionBP();
void setCandidateBP(std::list<Candidate> candidatesbp);
std::list<Candidate> getCandidateBP();
Candidate getCandidate(int index);
void ShowCandidates();
~BallotPaper();
};
#include "BallotPaper.h"
#include <string>
#include <iostream>
void BallotPaper::setPositionBP(PositionType positionbp)
{
_positionbp = positionbp;
}
PositionType BallotPaper::getPositionBP()
{
return _positionbp;
}
void BallotPaper::setCandidateBP(std::list<Candidate> candidatesbp)
{
_candidatesbp = candidatesbp;
}
std::list<Candidate> BallotPaper::getCandidateBP()
{
return _candidatesbp;
}
void BallotPaper::ShowCandidates()
{
for(Candidate c : _candidatesbp)
{
c->IncreaseVoteCount(); //ERROR!!!!
}
}
and this will be my candidate header and cpp file
class Candidate:public Member
{
private:
int _votecount;
PositionType _position;
public:
Candidate(std::string name, int id, std::string course, int contact, std::string joindate, PositionType currentposition) ;
~Candidate();
void setVoteCount(int votecount);
int getVoteCount();
void setPosition(PositionType position);
PositionType getPosition();
void IncreaseVoteCount(); //increase _votecount
};
#include "Candidate.h"
Candidate::Candidate()
{
_votecount = 0;
}
void Candidate::setVoteCount(int votecount)
{
_votecount = votecount;
}
int Candidate::getVoteCount()
{
return _votecount;
}
void Candidate::setPosition(PositionType position)
{
_position = position;
}
PositionType Candidate::getPosition()
{
return _position;
}
void Candidate::IncreaseVoteCount()
{
_votecount++;
}
I know is a super long code, and I appreciate for your patience in looking through it. My error is that it seems that it cannot recognize the function of "IncreaseVoteCount" in 'Candidate c'.
I have try to double check the syntax and the code for multiple times but i still don't understand what is the error here.

Static methods on boostcentric factory implementation

I'm trying to implement a C++ factory class that also perform the self registration of some derived classes. My implementation is based on the library:
http://arcticinteractive.com/2008/10/06/boost-centric-factory-pattern-implementation/
that is based on the Boost library. Just to give you a quick overview of this library, here is a simple self-explained (I hope) example:
struct foo { virtual ~foo() {} };
struct bar : foo { bar(int i) { std::cout << "bar() " << i << "\n"; } };
struct baz : foo { baz(int i) { std::cout << "baz() " << i << "\n"; } };
...
typedef factory< foo*(int) > myfactory_t;
myfactory_t f;
// Register a default (operator new) creator function
// for an implementation type
register_new_ptr<bar>(f, "bar");
register_new_ptr<baz>(f, "baz");
// Create objects through the factory
foo* fooimpl1 = f["bar"](1234);
foo* fooimpl2 = f["baz"](4321);
What I'm trying to do is to delegate each class to self-register them self to the factory using a static method. Here is the code:
animal.h
#pragma once
#include <cstring>
#include <iostream>
#include "factory.hpp"
#include "abstract_factory.hpp"
class zoo;
using namespace std;
using namespace boost::factory;
class animal{
virtual const std::string do_sound() const = 0;
std::string name_;
int age_;
zoo* myZoo_;
public:
animal(const std::string& name, int age, zoo* myZoo) : name_(name), age_(age), myZoo_(myZoo)
{}
virtual ~animal() {}
const std::string sound() const
{
return do_sound();
}
const std::string& name() const { return name_; }
const int age() const { return age_; }
};
template <class T>
struct animalFactory{
typedef factory< animal*(std::string&, int, zoo*) > myfactory_t;
static const myfactory_t* f;
static bool registerAnimal(const std::string& animalname){
return register_new_ptr<T>(&f, animalname);
};
};
When I try to register a class like:
crocodile.cpp
#include "crocodile.h"
bool r = animalFactory<crocodile>::registerAnimal("crocodile");
I get an error from visual studio 2012 that is:
animal.h(41): error C2893: Failed to specialize function template 'bool boost::factory::register_new_ptr(Factory &,Factory::id_param_type)'
Could someone help me to understand what is going on here? Thanks a lot!