I became a bit confused.
namespace Io
{
class IDevice;
}
//...
namespace Sensor
{
class IDevice;
}
//...
class ComplexDeviceHandler : public Io::IDevice, public Sensor::IDevice;
//...
std::vector<std::shared_ptr<Io::IDevice>> devices; //populated by objects of type ComplexDeviceHandler
//..
for (const auto& device : devices)
{
std::shared_ptr<Sensor::IDevice> sensor = device; //obviously, error here
}
Both Io::IDevice and Sensor::IDevice are interfaces (sort of).
What cast should I use to convert std::shared_ptr<Io::IDevice> to std::shared_ptr<Sensor::IDevice>. In this case, std::shared_ptr<Io::IDevice> stores an address of object of type ComplexDeviceHandler, which is a child of both types.
You need to first try to cast it to ComplexDeviceHandler*, check if it worked, and then it will be convertible to Sensor::IDevice*:
for (const auto& device: devices)
{
if (auto sidptr = std::dynamic_pointer_cast<ComplexDeviceHandler>(device)) {
std::shared_ptr<Sensor::IDevice> sensor = sidptr;
}
}
This is a coding example based on Holt's answer, which worked for me. (Very cool, Holt! Educational.) Hopefully mimics the OP use case scenario. I used C++17 in particular.
#include <cstddef>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
using std::cout;
using std::dynamic_pointer_cast;
using std::endl;
using std::make_shared;
using std::move;
using std::shared_ptr;
using std::string;
using std::vector;
class IFoo
{
virtual void DoFooStuff() = 0;
protected:
~IFoo() = default;
public:
void FooStuff();
};
void IFoo::FooStuff()
{
FooStuff();
}
class IBar
{
virtual void DoBarStuff() const = 0;
protected:
~IBar() = default;
public:
void BarStuff() const;
};
void IBar::BarStuff() const
{
DoBarStuff();
}
class Baz : public IFoo
{
virtual void DoFooStuff() override;
public:
};
void Baz::DoFooStuff()
{
cout << "Baz's DoFooStuff\n";
}
class Quuxplex : public IFoo, public IBar
{
virtual void DoFooStuff() override;
virtual void DoBarStuff() const override;
string s;
public:
Quuxplex(string);
void SecretSauce() const;
};
Quuxplex::Quuxplex(string sval) : s{move(sval)}
{ }
void Quuxplex::DoFooStuff()
{
cout << "Quuxplex's DoFooStuff with " << s << "\n";
}
void Quuxplex::DoBarStuff() const
{
cout << "Quuxplex's DoBarStuff with " << s << "\n";
}
void Quuxplex::SecretSauce() const
{
cout << "Quuxplex's SecretSauce with " << s << "\n";
}
int main()
{
vector<shared_ptr<IFoo>> things;
things.push_back(make_shared<Quuxplex>("pickle"));
things.push_back(make_shared<Baz>());
things.push_back(make_shared<Quuxplex>("relish"));
things.push_back(make_shared<Baz>());
things.push_back(make_shared<Quuxplex>("mustard"));
vector<shared_ptr<Quuxplex>> quuxplexes;
int found = 0;
for (auto const& thing : things)
{
if (auto q = dynamic_pointer_cast<Quuxplex>(thing))
{
++found;
q->SecretSauce();
quuxplexes.push_back(q);
cout << "Quuxplex objects found: " << found << " count: " << q.use_count() << endl;
}
}
return EXIT_SUCCESS;
}
Related
A performance bottleneck of my program is frequent calls to functions like following update functions.
Given that flag parameter is always a bool literal, I want to "unroll" the update function to two versions, one with flag=true and one with flag=false, to avoid branch prediction failure.
for normal functions, a bool template parameter can solve this problem easily.
However, template cannot be applied to virtual functions.
I can create two virtual functions manually, but then I have to copy the long code part. It makes futher development harder.
Is there anyway allowing me to write two versions in one function, controlled by a compiling-time constant flag?
#include <iostream>
#include <random>
using std::cout;
using std::endl;
struct Base
{
virtual void update(bool flag) = 0;
};
struct Derived1 : public Base
{
void update(bool flag)
{
if (flag)
{
// some computations
cout << "Derived1 flag=true" << endl;
}
else
{
// some computations
cout << "Derived1 flag=false" << endl;
}
// long code containing several flag-conditioned blocks like the block above
cout << "Derived1" << endl;
}
};
struct Derived2 : public Base
{
void update(bool flag)
{
if (flag)
{
// some computations
cout << "Derived2 flag=true" << endl;
}
else
{
// some computations
cout << "Derived2 flag=false" << endl;
}
// long code containing several flag-conditioned blocks like the block above
cout << "Derived2" << endl;
}
};
int main()
{
Base *p;
srand(time(nullptr));
if (rand() % 2 == 1)
{
p = new Derived1();
}
else
{
p = new Derived2();
}
p->update(false);
p->update(true);
}
Unfortunately, there is no such thing as virtual templates. What can be done however is to create several virtual functions taking an integral (boolean in this particular case) constant, if the flag is really a compile time literal:
#include <iostream>
#include <random>
#include <type_traits>
#include <memory>
using std::cout;
struct Base
{
virtual void updateSeparate(std::true_type) = 0;
virtual void updateSeparate(std::false_type) = 0;
};
struct Derived1 : public Base
{
void updateSeparate(std::true_type)
{
cout << "Derived1 flag=true\n";
updateCommonImpl();
}
void updateSeparate(std::false_type)
{
cout << "Derived1 flag=false\n";
updateCommonImpl();
}
private:
void updateCommonImpl() //or just a static function inside implementation file if members are not used
{
cout << "Derived1\n";
}
};
struct Derived2 : public Base
{
void updateSeparate(std::true_type)
{
cout << "Derived2 flag=true\n";
updateCommonImpl();
}
void updateSeparate(std::false_type)
{
cout << "Derived2 flag=false\n";
updateCommonImpl();
}
private:
void updateCommonImpl() //or just a static function inside implementation file if members are not used
{
cout << "Derived2\n";
}
};
int main()
{
std::unique_ptr<Base> p;
srand(time(nullptr));
if (rand() % 2 == 1)
{
p = std::make_unique<Derived1>();
}
else
{
p = std::make_unique<Derived2>();
}
p->updateSeparate(std::bool_constant<false>{});
p->updateSeparate(std::bool_constant<true>{});
}
DEMO
However, I cannot tell if that will help or maybe hinder the performance even more by making the vtable lookup time even longer, you have to experiment with that by yourself I'm afraid.
I tried to implement a CRTP pattern with constexpr template parameter, please take a look
template<typename T>
struct Base {
template<bool flag>
int update() {
return static_cast<T*>(this)->template updateImpl<flag>();
}
};
struct Derived1 : public Base<Derived1> {
template<bool flag>
constexpr int updateImpl() {
if constexpr (flag) {
return 1;
} else {
return 2;
}
}
};
struct Derived2 : public Base<Derived2> {
template<bool flag>
constexpr int updateImpl() {
return 3;
}
};
int main() {
auto obj1 = new Derived1();
std::cout << obj1->update<true>(); // 1
std::cout << obj1->update<false>(); // 2
auto obj2 = new Derived2();
std::cout << obj2->update<true>(); // 3
std::cout << obj2->update<false>(); // 3
}
I want to store some data to container. For example I have such code:
#include <iostream>
#include <string>
#include <memory>
#include <map>
class Base
{
public:
Base() {}
virtual ~Base() {}
};
class Class1 : public Base
{
public:
Class1() : Base() {}
~Class1() {}
};
class Class2 : public Base
{
public:
Class2() : Base() {}
~Class2() {}
};
class Class3 : public Base
{
public:
Class3() : Base() {}
~Class3() {}
};
std::map<std::string, std::shared_ptr<Base>> myContainer;
void save(const std::string& id, std::shared_ptr<Base> obj)
{
auto obj1 = std::dynamic_pointer_cast<Class1>(obj);
if (obj1)
{
std::cout << "save obj1" << std::endl;
myContainer.emplace(std::piecewise_construct,
std::make_tuple(id),
std::make_tuple(std::move(obj1))
);
}
auto obj2 = std::dynamic_pointer_cast<Class2>(obj);
if (obj2)
{
std::cout << "save obj2" << std::endl;
myContainer.emplace(std::piecewise_construct,
std::make_tuple(id),
std::make_tuple(std::move(obj2))
);
}
auto obj3 = std::dynamic_pointer_cast<Class3>(obj);
if (obj3)
{
std::cout << "save obj3" << std::endl;
myContainer.emplace(std::piecewise_construct,
std::make_tuple(id),
std::make_tuple(std::move(obj3))
);
}
}
int main()
{
std::shared_ptr<Class1> a1 = std::make_shared<Class1>();
std::shared_ptr<Class2> a2 = std::make_shared<Class2>();
std::shared_ptr<Class3> a3 = std::make_shared<Class3>();
save("id1", a1);
save("id2", a2);
save("id3", a3);
std::cout << "size is " << myContainer.size() << std::endl;
return 0;
}
But function save() has too much complicated implementation. How to make it easier? Somehow to get correct object type and invoke save() once but not in every checking. Maybe it possible to implement it with std::variant or std::tuple? What is much optimized solution you can propose?
You seem to understand virtual functions.
Your entire save function could be implemented as:
void save(const std::string& id, std::shared_ptr<Base> obj)
{
std::cout << "save " << obj->name() << std::endl;
myContainer.emplace(std::piecewise_construct,
std::make_tuple(id),
std::make_tuple(std::move(obj))
);
}
name() would be a virtual function that returns the correct string for the type.
Note that this implementation always saves the pointer passed to it, while your implementation may not save anything.
Assuming you've provide a shared pointer containing the real class instead of a std::shared_ptr<Base> when calling the function, you can rewrite this as a template:
template<class T>
char const* TypeName();
template<>
char const* TypeName<Class1>() { return "obj1"; }
template<>
char const* TypeName<Class2>() { return "obj2"; }
template<>
char const* TypeName<Class3>() { return "obj3"; }
template<class T>
void save(const std::string& id, std::shared_ptr<T> obj)
{
std::cout << "save " << TypeName<T>() << std::endl;
myContainer.emplace(std::piecewise_construct,
std::make_tuple(id),
std::make_tuple(std::move(obj))
);
}
In C ++, I first encountered function pointers.
I tried to use this to make it similar to Action and Delegate in C #.
However, when declaring a function pointer, it is necessary to specify the type of the class in which the function exists.
ex) void (A :: * F) ();
Can I use a function pointer that can store a member function of any class?
In general, function pointers are used as shown in the code below.
class A {
public:
void AF() { cout << "A::F" << endl; }
};
class B {
public:
void(A::*BF)();
};
int main()
{
A a;
B b;
b.BF = &A::AF;
(a.*b.BF)();
return 0;
}
I want to use it like the code below.
is this possible?
Or is there something else to replace the function pointer?
class A {
public:
void AF() { cout << "A::F" << endl; }
};
class B {
public:
void(* BF)();
};
int main()
{
A a;
B b;
b.BF = a.AF;
return 0;
}
I solved the question through the answer.
Thanks!
#include <functional>
#include <iostream>
class A {
public:
void AF() { std::cout << "A::F" << std::endl; }
};
class C {
public:
void CF() { std::cout << "C::F" << std::endl; }
};
class B {
public:
B(){}
std::function<void()> BF;
};
int main() {
A a;
C c;
B b;
b.BF = std::bind(&A::AF, &a);
b.BF();
b.BF = std::bind(&C::CF, &c);
b.BF();
int i;
std::cin >> i;
return 0;
}
What you want to do is probably something like this. You can use std::function to hold a pointer to a member function bound to a specific instance.
#include <functional>
#include <iostream>
class A {
public:
void AF() { std::cout << "A::F" << std::endl; }
};
class B {
public:
B(const std::function<void()>& bf) : BF(bf) {}
std::function<void()> BF;
};
int main() {
A a;
B b1(std::bind(&A::AF, &a)); // using std::bind
B b2([&a] { a.AF(); }); // using a lambda
b1.BF();
b2.BF();
return 0;
}
Here's a C# style implementation of the accepted answer, It is memory efficient and flexible as you can construct and delegate at different points of execution which a C# developer might expect to do:
#include <iostream>
#include <functional>
using namespace std;
class A {
public:
void AF() { cout << "A::F" << endl; }
void BF() { cout << "B::F" << endl; }
};
class B {
public:
std::function<void()> Delegate;
};
int main() {
A a;
B b;
b.Delegate = std::bind(&A::AF, &a);
b.Delegate();
b.Delegate = [&a] { a.BF(); };
b.Delegate();
return 0;
}
Usually when I see tutorials about Observer Pattern I see an unique method called notify, but I'm wondering. What if I have different methods that can be called in different moments but needs to notify the others when this happen? Like events, am I doing this wrong? or still begin the observer pattern?
#include <iostream>
#include <algorithm>
#include <vector>
class Observer
{
public:
virtual void notifyBefore() = 0;
virtual void notifyAfter() = 0;
};
class Subject
{
public:
void attachObserver(Observer * observer)
{
observers.push_back(observer);
}
void detachObserver(Observer * observer)
{
auto index = std::find(observers.begin(), observers.end(), observer);
if (index != observers.end())
{
observers.erase(index);
}
}
virtual void notifyBefore()
{
for (auto current : observers)
{
current->notifyBefore();
}
}
virtual void notifyAfter()
{
for (auto current : observers)
{
current->notifyAfter();
}
}
private:
std::vector<Observer *> observers;
};
class ConcreteObserver : public Observer
{
public:
void notifyBefore()
{
std::cout << "You called me before..." << std::endl;
}
void notifyAfter()
{
std::cout << "You called me after..." << std::endl;
}
};
class ConcreteSubject : public Subject
{
public:
};
int main()
{
auto subject = new ConcreteSubject;
subject->attachObserver(new ConcreteObserver);
subject->notifyBefore();
for (int i = 0; i < 5; ++i)
std::cout << i << std::endl;
subject->notifyAfter();
}
Is it still an observer pattern? sure
You created an observer pattern with 2 types of events/notifications.
You could have written it as:
void notify(Type type);
Where Type is the type of event (e.g. an enum).
You can also pass other parameters to indicate other parameters relevant to the event.
void notify(Type type, std::string value);
This is the example code I have:
#include <iostream>
#include <vector>
#include <string>
class Animal {
};
class Rabbit : public Animal {
};
class Caller {
public:
virtual void call(Animal* a) {
std::cout << "Caller calls animal" << std::endl;
}
virtual void call(Rabbit* r) {
std::cout << "Caller calls rabbit" << std::endl;
}
};
int main(int argc, char** argv) {
std::vector<Animal*> v;
Caller c;
auto a = new Animal();
auto r = new Rabbit();
v.push_back(a);
v.push_back(r);
for(auto elem : v) {
c.call(elem);
}
return 0;
}
The output of this code can be found here
http://ideone.com/I29g3A
and it outputs:
Caller calls animal
Caller calls animal
I'm wondering, without casting a specific element to Rabbit*, is there a way to get call(Rabbit *r) method to get called?
Sure, e.g., by jumping through a suitable visitor in your system of polymorphic classes. I think you'll need to use two names instead of call(), however. I used pubCall() and call().
#include <iostream>
#include <vector>
#include <string>
class Visitor;
class Animal {
public:
virtual void visit(Visitor&);
};
class Rabbit : public Animal {
void visit(Visitor&);
};
class Visitor
{
public:
virtual void call(Animal* a) = 0;
virtual void call(Rabbit* r) = 0;
};
void Animal::visit(Visitor& v) {
v.call(this);
}
void Rabbit::visit(Visitor& v) {
v.call(this);
}
class Caller
: Visitor {
public:
void pubCall(Animal* a) { a->visit(*this); }
private:
virtual void call(Animal* a) {
std::cout << "Caller calls animal" << std::endl;
}
virtual void call(Rabbit* r) {
std::cout << "Caller calls rabbit" << std::endl;
}
};
int main(int argc, char** argv) {
std::vector<Animal*> v;
Caller c;
auto a = new Animal();
auto r = new Rabbit();
v.push_back(a);
v.push_back(r);
for(auto elem : v) {
c.pubCall(elem);
}
return 0;
}