Calling thread on member function - c++

Sorry for the long example, but the question is simple. I'm using basic Visitor Pattern, with a mediator to manage several concrete Visitor_pick : public DataVisitor objects. The conrete mediator, SimulatorMediator, fills a list with Visitor_pick objects, then wants to call std::thread on a DataVisitor member function. I have tried several variants, using mem_fun1_t<>, etc., with no luck. Can't compile. What is the correct syntax?
The call in question should be at line 205 - I'd like to attach threads to v->visit_SpreadData, a unary function, then populate threadVec. Any help would be appreciated.
#include <iostream>
#include <ostream>
#include <iterator>
#include <list>
#include <vector>
#include <algorithm>
#include <thread>
class PublishEvent;
class Subscriber
{
public:
virtual void update(const PublishEvent *e) = 0;
~Subscriber() = default;
};
class Publisher
{
public:
void attach(Subscriber*);
void detach(Subscriber*);
void notify(const PublishEvent*);
protected:
std::list<Subscriber*> subscribers_;
};
inline void Publisher::
notify(const PublishEvent *e)
{
for (auto &s : subscribers_)
s->update(e);
}
inline void Publisher::
attach(Subscriber *s)
{
subscribers_.push_back(s);
}
inline void Publisher::
detach(Subscriber *s)
{
// inefficient for large nubmer of susbscribers
subscribers_.remove(s);
}
class Mediator;
class SpreadData;
class DataElement;
class DataVisitor : public Publisher, public Subscriber
{
public:
virtual ~DataVisitor() {}
// visit method
virtual void visit_SpreadData(SpreadData *SD) = 0;
// from Publisher::
void update(const PublishEvent *e) override;
void setMediator(Mediator *m)
{
m_ = m;
}
float get_payload() const
{
return payload_;
}
void set_payload(float p)
{
payload_ = p;
}
virtual void gendata(DataElement*) = 0;
protected:
DataVisitor() {}
private:
Mediator *m_;
float payload_;
};
class DataElement
{
public:
virtual ~DataElement() {};
void Accept(DataVisitor&);
protected:
DataElement() {};
};
void DataElement::Accept(DataVisitor &d)
{
d.gendata(this);
}
class SpreadData : public DataElement
{
public:
typedef std::vector<float> return_data_type;
SpreadData() { initiate(); };
SpreadData(std::string filename) { initiate();};
void printdata() const
{
std::copy(data_.begin(),
data_.end(),
std::ostream_iterator<float>(std::cout, " : "));
std::cout << std::endl;
}
return_data_type getdata() const
{
return data_;
}
private:
void initiate()
{
for(int i=0;i<100;i++)
data_.push_back(static_cast<float>(i));
}
return_data_type data_;
};
void DataVisitor::update(const PublishEvent *e)
{
// implementation details
};
template<int N>
class Visitor_pick : public DataVisitor
{
public:
Visitor_pick()
{set_payload(0.); }
// from DataVisitor
void visit_SpreadData(SpreadData*) override;
// from DataVisitor
void gendata(DataElement*);
};
template<int N>
void Visitor_pick<N>::visit_SpreadData(SpreadData *SD)
{
SD->Accept(*this);
}
template<int N>
void Visitor_pick<N>::gendata(DataElement *d)
{
// implementation details
SpreadData *SD = dynamic_cast<SpreadData*>(d);
SpreadData::return_data_type r = SD->getdata();
set_payload(r[N]);
}
class Mediator
{
public:
virtual ~Mediator() = default;
virtual void mediate(DataElement*) = 0;
protected:
Mediator() = default;
virtual void CreateVisitors() = 0;
std::list<DataVisitor*> visitors_;
};
class Mediator_1 : public Mediator
{
public:
Mediator_1()
{
CreateVisitors();
}
void mediate(DataElement*);
private:
void CreateVisitors();
};
void Mediator_1::CreateVisitors()
{
visitors_.push_back(new Visitor_pick<37>());
visitors_.push_back(new Visitor_pick<42>());
visitors_.push_back(new Visitor_pick<47>());
visitors_.push_back(new Visitor_pick<52>());
visitors_.push_back(new Visitor_pick<57>());
}
void Mediator_1::mediate(DataElement *SD)
{
typedef std::mem_fun1_t<void,DataVisitor,SpreadData*> Visitor_fn;
std::cout << "Mediating hard..." << std::endl;
std::vector<std::thread> threadVec;
for(auto &v : visitors_)
{
// Use Visitor_fn to spawn thread on
// unary function v->visit_SpreadData,
// place at back of threadVec
}
for_each(threadVec.begin(), threadVec.end(),
std::mem_fn(&std::thread::join));
for(auto &v : visitors_)
std::cout << "Payload: " << v->get_payload() << std::endl;
}
int main(int argc, char **argv)
{
SpreadData *SD = new SpreadData();
Mediator_1 *M = new Mediator_1();
M->mediate(SD);
delete SD;
delete M;
return 0;
}

Related

How to get a subtype object saved in a supertype object to be recognized as a subtype

I have this problem which I really struggle to even explain(as you can guess by the title) so I'll make it clear by an example
#include <iostream>
using namespace std;
class shape
{
public:
shape()
{
}
};
class triangle : public shape
{
public:
triangle()
{
}
};
class square : public shape
{
public:
square()
{
}
};
class shapeTeller
{
public:
shapeTeller() {}
void tellMeWhatShape(square s)
{
cout << "Hello, I'm a square\n";
}
void tellMeWhatShape(triangle t)
{
cout << "Hello, I'm a triangle\n";
}
void tellMeWhatShape(shape s)
{
cout << "Hello, I'm a generic shape\n";
}
};
int main()
{
shape sh;
triangle tr;
square sq;
shape shapeArray[3] = {sh, tr, sq};
shapeTeller tell;
for (auto &element : shapeArray)
{
tell.tellMeWhatShape(element);
}
}
this snippet of code prints three times "Hello, I'm a generic shape", while my desired output would be
"Hello, I'm a generic shape"
"Hello, I'm a triangle"
"Hello, I'm a square"
How can i achieve something like that, considering that I want the array to be of the superclass, and I want it to contains various subclasses?
I also want to make it clear that this is a simplified exhample but in the real implementation I can't use parametric polymorphism cause i want the shapeTeller class' methods to do completely different things.
Thanks a lot
Note: An array can only store a single type of object. A subtype of the object could be an entirely different size which is not something compatible with the way C++ stores arrays.
You could be using std::variant here to allow every array element to store one of several element types here:
class shapeTeller
{
public:
shapeTeller() {}
void tellMeWhatShape(square s)
{
std::cout << "Hello, I'm a square\n";
}
void tellMeWhatShape(triangle t)
{
std::cout << "Hello, I'm a triangle\n";
}
void tellMeWhatShape(shape s)
{
std::cout << "Hello, I'm a generic shape\n";
}
void tellMeWhatShape(std::variant<square, triangle, shape> const& s)
{
std::visit([this](auto const& shape)
{
tellMeWhatShape(shape);
},
s);
}
};
int main()
{
shape sh;
triangle tr;
square sq;
std::variant<square, triangle, shape> shapeArray[3] = { sh, tr, sq };
shapeTeller tell;
for (auto& element : shapeArray)
{
tell.tellMeWhatShape(element);
}
}
Alternatively dynamically allocate the shapes and implement the visitor pattern:
class shape;
class triangle;
class square;
struct Visitor
{
virtual void operator()(shape const&) = 0;
virtual void operator()(triangle const&) = 0;
virtual void operator()(square const&) = 0;
};
class shape
{
public:
virtual ~shape() = default;
shape()
{
}
virtual void Accept(Visitor& v) const
{
v(*this);
}
};
class triangle : public shape
{
public:
triangle()
{
}
void Accept(Visitor& v) const override
{
v(*this);
}
};
class square : public shape
{
public:
square()
{
}
void Accept(Visitor& v) const override
{
v(*this);
}
};
class shapeTeller
{
public:
shapeTeller() {}
void tellMeWhatShape(square s)
{
std::cout << "Hello, I'm a square\n";
}
void tellMeWhatShape(triangle t)
{
std::cout << "Hello, I'm a triangle\n";
}
void tellMeWhatShape(shape s)
{
std::cout << "Hello, I'm a generic shape\n";
}
};
int main()
{
auto sh = std::make_unique<shape>();
auto tr = std::make_unique<triangle>();
auto sq = std::make_unique<square>();
std::unique_ptr<shape> shapeArray[3] = { std::move(sh), std::move(tr), std::move(sq) };
shapeTeller tell;
struct ShapeTellerVisitor : Visitor
{
ShapeTellerVisitor(shapeTeller& teller)
: m_teller(teller)
{}
shapeTeller& m_teller;
virtual void operator()(shape const& s) override
{
m_teller.tellMeWhatShape(s);
}
virtual void operator()(triangle const& s) override
{
m_teller.tellMeWhatShape(s);
}
virtual void operator()(square const& s) override
{
m_teller.tellMeWhatShape(s);
}
};
ShapeTellerVisitor visitor{ tell };
for (auto& element : shapeArray)
{
element->Accept(visitor);
}
}
Note: You could implement Visitor with shapeTeller directly.

Polymorphism with std::variant perfomances

Having a closer look at __do_visit in std::variant I grew curious about the performances of the std::variant polymorphic approach
I wrote a small test program to compare old school inheritance to the std::variant one
#include <variant>
#include <vector>
#include <iostream>
#include <string>
#include <chrono>
int i = 0;
// Polymorphism using variants
class circle
{
public:
void draw() const { i++; }
};
class line
{
public:
void draw() const { i++; }
};
using v_t = std::variant<circle, line>;
void variant_way(const std::vector<v_t>& v)
{
for (const auto &var : v)
std::visit([](const auto& o) {
o.draw();
}, var);
}
// old school
class shape
{
public:
virtual void draw() const = 0;
virtual ~shape() { }
};
class circle_in : public shape
{
public:
virtual void draw() const { i++; }
};
class line_in : public shape
{
public:
virtual void draw() const { i++; }
};
void inherit_way(const std::vector<shape*>& v)
{
for (const auto var : v)
var->draw();
}
// call and measure
template <typename F, typename D>
void run(F f, const D& data, std::string name)
{
auto start = std::chrono::high_resolution_clock::now();
f(data);
auto end = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << name << ": "<< elapsed.count() << std::endl;
}
int main()
{
constexpr int howmany = 100000;
{
std::vector<v_t> v {howmany};
run(variant_way, v, "variant");
}
{
std::vector<shape*> v;
for (int i = 0; i < howmany; i++)
v.push_back(new circle_in());
run(inherit_way, v, "inherit_way");
// deallocate
}
return 0;
}
On my machine (i7, 16GB RAM), I get these results:
variant: 7487
inherit_way: 1302
I suspect that this result reflects the fact that the std::variant approach creates the vtable at each iteration while the inheriting approach does it once for all.
Is this explanation correct?
Is there a way to reduce the overhead?

C++ self-registering factory, multi parameters constructors

I read this article about C++ factory class with a self registering capability of the concrete classes. Really like it, expecially the demangled name solution used as a key for the registered classes.
There is one main issue I would like to solve: how can we modify the factory to be able to support concrete classes with different constructor parameters?
// Dog and Cat both derive from Animal, but have different constructor parameters
class Dog : public Animal::Registrar<Dog> {
public:
Dog(int param1, std::string param2) : m_x(param1) {}
void makeNoise() { std::cerr << "Dog: " << m_x << "\n"; }
private:
int m_x;
};
class Cat : public Animal::Registrar<Cat> {
public:
Cat(bool param1) : m_flag(param1) {}
void makeNoise() { std::cerr << "Cat: " << m_x << "\n"; }
private:
bool m_flag;
};
I was thinking that maybe the parameter pack of template <class Base, class... Args> class Factory should be moved to the template <class T> struct Registrar, but I can't found a proper solution.
Full original code below
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <cstdlib>
#include <cxxabi.h>
std::string demangle(const char *name) {
int status = -4; // some arbitrary value to eliminate the compiler warning
std::unique_ptr<char, void (*)(void *)> res{
abi::__cxa_demangle(name, NULL, NULL, &status), std::free};
return (status == 0) ? res.get() : name;
}
template <class Base, class... Args> class Factory {
public:
template <class ... T>
static std::unique_ptr<Base> make(const std::string &s, T&&... args) {
return data().at(s)(std::forward<T>(args)...);
}
template <class T> struct Registrar : Base {
friend T;
static bool registerT() {
const auto name = demangle(typeid(T).name());
Factory::data()[name] = [](Args... args) -> std::unique_ptr<Base> {
return std::make_unique<T>(std::forward<Args>(args)...);
};
return true;
}
static bool registered;
private:
Registrar() : Base(Key{}) { (void)registered; }
};
friend Base;
private:
class Key {
Key(){};
template <class T> friend struct Registrar;
};
using FuncType = std::unique_ptr<Base> (*)(Args...);
Factory() = default;
static auto &data() {
static std::unordered_map<std::string, FuncType> s;
return s;
}
};
template <class Base, class... Args>
template <class T>
bool Factory<Base, Args...>::Registrar<T>::registered =
Factory<Base, Args...>::Registrar<T>::registerT();
struct Animal : Factory<Animal, int> {
Animal(Key) {}
virtual void makeNoise() = 0;
};
class Dog : public Animal::Registrar<Dog> {
public:
Dog(int x) : m_x(x) {}
void makeNoise() { std::cerr << "Dog: " << m_x << "\n"; }
private:
int m_x;
};
class Cat : public Animal::Registrar<Cat> {
public:
Cat(int x) : m_x(x) {}
void makeNoise() { std::cerr << "Cat: " << m_x << "\n"; }
private:
int m_x;
};
// Won't compile because of the private CRTP constructor
// class Spider : public Animal::Registrar<Cat> {
// public:
// Spider(int x) : m_x(x) {}
// void makeNoise() { std::cerr << "Spider: " << m_x << "\n"; }
// private:
// int m_x;
// };
// Won't compile because of the pass key idiom
// class Zob : public Animal {
// public:
// Zob(int x) : Animal({}), m_x(x) {}
// void makeNoise() { std::cerr << "Zob: " << m_x << "\n"; }
// std::unique_ptr<Animal> clone() const { return
// std::make_unique<Zob>(*this); }
// private:
// int m_x;
// };
// An example that shows that rvalues are handled correctly, and
// that this all works with move only types
struct Creature : Factory<Creature, std::unique_ptr<int>> {
Creature(Key) {}
virtual void makeNoise() = 0;
};
class Ghost : public Creature::Registrar<Ghost> {
public:
Ghost(std::unique_ptr<int>&& x) : m_x(*x) {}
void makeNoise() { std::cerr << "Ghost: " << m_x << "\n"; }
private:
int m_x;
};
int main() {
auto x = Animal::make("Dog", 3);
auto y = Animal::make("Cat", 2);
x->makeNoise();
y->makeNoise();
auto z = Creature::make("Ghost", std::make_unique<int>(4));
z->makeNoise();
return 0;
}

upcasting variable in derived class c++

How to change the type of a inherited variable in the derived class?
I have the following classes:
class Position;
class StonePosition;
class Position {
public:
Position() {}
};
class StonePosition : public Position {
int count;
public:
StonePosition(const int count) { this->count = count; }
int getCount() { return this->count; }
void setCount(int count) { this->count = count; }
friend ostream& operator<<(ostream&, StonePosition);
};
class Board {
protected:
Position* crrPos;
public:
Board() { }
Position* getCrrPos() { return crrPos; }
void setCrrPos(Position* pos) { crrPos=pos; }
};
class StoneBoard : public Board {
public:
StoneBoard(const int &count) { this->crrPos=new StonePosition(count); } //<----------------
StonePosition* getCrrPos() { return (StonePosition*)crrPos; }
void setCrrPos(StonePosition* pos) { crrPos=pos; }
};
Place in which the problem is marked by an arrow. I need to change the type of a variable from Position to StonePosition in the StoneBoard class. I found an option that can be used upcasting, but it works only within a single method, and I need to change the variable for the entire class.
The problem was solved, look at my answer.
The variable "crrPos" is not of type Position it is of type pointer to Position and this is significant because a pointer to Position can point to a Position or a class derived from Position without losing anything.
If you design your classes well, and make use of virtual functions, you can usually avoid the need to upcast entirely.
#include <iostream>
class Base {
public:
virtual void foo() { std::cout << "Base::foo()\n"; }
virtual bool isDerived() const { return false; }
};
class Derived : public Base {
public:
void foo() override { std::cout << "Derived::foo()\n"; }
bool isDerived() const { return true; }
};
int main() {
Base* crrPos = new Derived;
crrPos->foo();
bool isDerived = crrPos->isDerived();
std::cout << isDerived << '\n';
delete crrPos;
}
Live demo: http://ideone.com/UKcBaA
The problem has been solved, I just use the projection ((StonePosition*)Position*):
#include <iostream>
using namespace std;
class Position;
class StonePosition;
class Position {
public:
Position() {}
};
class StonePosition : public Position {
int count;
public:
StonePosition(const int count) { this->count = count; }
int getCount() { return this->count; }
void setCount(int count) { this->count = count; }
friend ostream& operator<<(ostream&, StonePosition);
};
template <typename TPos> class TBoard {
protected:
TPos* crrPos;
public:
TBoard() { }
TPos* getCrrPos() { return crrPos; }
void setCrrPos(TPos* pos) { crrPos=pos; }
};
class Board {
protected:
Position* crrPos;
public:
Board() { }
Position* getCrrPos() { return crrPos; }
void setCrrPos(Position* pos) { crrPos=pos; }
};
class StoneBoard : public Board {
public:
StoneBoard(const int &count) { this->crrPos=new StonePosition(count); }
Position* getCrrPos() { return crrPos; }
void setCrrPos(Position* pos) { crrPos=pos; }
};
int main(){
StoneBoard s(7);
cout<<((StonePosition*)s.getCrrPos())->getCount();//<----right here
system("pause");
return 0;
}
And its working nice :)

Using a Wrapper for memory management in c++

Could anyone tell me why i get a compiling error in the "setFlyBehaviour" and "setQuackBehaviour" of the Duck class? (error : "term does not evaluate to a function taking 1 arguments")
this is an example of a strategy pattern from Head First Design Patterns (which is in Java that i translated here in C++). I introduced a Wrapper pattern in order to manage memory. (the wrapper class i'm using is from Mark Joshi, Option Pricing and Design Patterns)
Thanks!!!!!
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string>
#include <map>
#include <exception>
#include <vector>
using namespace std;
template< class T>
class Wrapper
{
//Taken From Mark Joshi, Designs patterns and derivatives pricing
public:
Wrapper()
{ DataPtr =0;}
Wrapper(const T& inner)
{
DataPtr = inner.clone();
}
Wrapper(const Wrapper<T>& original)
{
if (original.DataPtr !=0)
DataPtr = original.DataPtr->clone();
else
DataPtr=0;
}
~Wrapper()
{
if (DataPtr !=0)
delete DataPtr;
}
Wrapper& operator=(const Wrapper<T>& original)
{
if (this != &original)
{
if (DataPtr!=0)
delete DataPtr;
DataPtr = (original.DataPtr !=0) ? original.DataPtr->clone() : 0;
}
return *this;
}
T& operator*()
{
return *DataPtr;
}
const T& operator*() const
{
return *DataPtr;
}
const T* const operator->() const
{
return DataPtr;
}
T* operator->()
{
return DataPtr;
}
private:
T* DataPtr;
};
/*****************************************************/
/***************** Interfaces ****************/
/*****************************************************/
class FlyBehaviour
{
private:
public:
virtual void fly() const = 0;
virtual FlyBehaviour* clone() const = 0;
};
class QuackBehaviour
{
private:
public:
virtual void quack() const = 0;
virtual QuackBehaviour* clone() const = 0;
};
/*****************************************************/
/***************** Implementations ***********/
/*****************************************************/
// -- FlyBehaviour
class FlyWithWings : public FlyBehaviour
{
public:
virtual void fly() const{
cout << "flying with wings" << endl;
}
virtual FlyBehaviour* clone() const {
return new FlyWithWings;
}
};
class FlyNoWay : public FlyBehaviour
{
public:
virtual void fly() const{
cout << "flying no way" << endl;
}
virtual FlyBehaviour* clone() const {
return new FlyNoWay;
}
};
// -- QuackBehaviour
class Quack : public QuackBehaviour
{
public:
virtual void quack() const{
cout << "Quacking here!" << endl;
}
virtual QuackBehaviour* clone() const{
return new Quack;
}
};
class Squeak : public QuackBehaviour
{
public:
virtual void quack() const{
cout << "Squeaking here!" << endl;
}
virtual QuackBehaviour* clone() const{
return new Squeak;
}
};
class Duck
{
private:
Wrapper<FlyBehaviour> flyBehaviour;
Wrapper<QuackBehaviour> quackBehaviour;
public:
void performQuack() const{
quackBehaviour->quack();
}
void performFly() const{
flyBehaviour->fly();
}
void setFlyBehaviour(const FlyBehaviour& mfly){
flyBehaviour(mfly);
}
void setQuackBehaviour(const FlyBehaviour& mquack){
quackBehaviour(mquack);
}
virtual void display() const{
}
};
class MallardDuck : public Duck
{
public:
virtual void display() const{
cout << "It looks like a Mallar" << endl;
}
};
class RedheadDuck : public Duck
{
public:
virtual void display() const{
cout << "It looks like a Redhead" << endl;
}
};
int main()
{
}
You were actually trying to call non-existent function instead of constructor.
There was also mistake in argument you were passing to setQuackBehaviour.
This should work:
void setFlyBehaviour(const FlyBehaviour& mfly){
flyBehaviour = mfly;
}
void setQuackBehaviour(const QuackBehaviour& mquack){
quackBehaviour = mquack;
}
It fails because Wrapper does not provide function call operator:
R T::operator ()(Arg1 a1, Arg2 a2, …)
And you are trying to make a call to Wrapper template:
flyBehaviour(mfly);
#werewindle like this ?
void reset(const QuackBehaviour& original){
if (DataPtr!= &original)
{
if (DataPtr!=0)
delete DataPtr;
DataPtr = (original.DataPtr !=0) ? original.DataPtr->clone() : 0;
}
}