I have following classes:
class ATemperatureDevice{};
class AHumidityDevice{};
class BluetoothLeDevice{};
class Sensor1 : BluetoothLeDevice, ATemperatureDevice, AHumidityDevice {};
class Sensor2 : BluetoothLeDevice, AHumidityDevice {};
I have a vector<BluetoothLeDevice*>, where all devices are stored.
The Classes ATemperatureDevice, AHumidityDevice and BluetoothLeDevice have virtual functions.
When I pick one, I have a BluetoothLeDevice. Now I want to check if it derives from ATemperatureDevice and/or AHumidityDevice.
I tried dynamic_cast, when its not castable, I should get null but, it says "'dynamic_cast' not permitted with -fno-rtti" although they have virtual functions.
What's the best way to check and cast?
As people already commented, storing polymorphic objects T inside a std::vector<T> will cause object slicing. Your code makes sense in C#, but in C++ people tend to use composition over inheritance whenever possible to avoid such issues. In your case this could look like: https://godbolt.org/z/xna1vjnWh
If dynamic_cast is not permitted, then store tag to identify derived class.
// Test sample
#include <iostream>
using namespace std;
class BluetoothLeDevice
{
public:
enum class DerivedClassMetaInfo
{
Sensor1Tag,
Sensor2Tag
};
virtual ~BluetoothLeDevice()
{
}
virtual DerivedClassMetaInfo tag(void) const = 0;
template <typename TargetType>
TargetType& to()
{
if (TargetType::static_tag != tag())
throw "Convertion failed";
return static_cast<TargetType&>(*this);
}
};
class Sensor1 : public BluetoothLeDevice
{
public:
static const BluetoothLeDevice::DerivedClassMetaInfo static_tag = BluetoothLeDevice::DerivedClassMetaInfo::Sensor1Tag;
void show()
{
cout << "Sensor1 message" << endl;
}
virtual DerivedClassMetaInfo tag(void) const override
{
return static_tag;
}
};
int main()
{
BluetoothLeDevice* temp = new Sensor1();
Sensor1& sens = temp->to<Sensor1>();
sens.show();
delete temp;
return 0;
}
Note: use this code with cautions, because it does not handle tricky inheritance trees. However you can easy (I guess) improve it
Related
I have an abstract base class called BaseStrategy. It contains one pure virtual function calculateEfficiency(). There are two classes ConvolutionStrategy and MaxPoolStrategy which derive from this base class and implement their own specific version of calculateEfficiency().
Here is some code:
class BaseStrategy {
public:
explicit BaseStrategy();
virtual ~BaseStrategy() = default;
private:
virtual double calculateEfficiency(mlir::Operation* op) = 0;
};
class ConvolutionStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for convolution
return 1;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for MaxPool
return 1;
}
};
Now I have another class called StrategyAssigner. It has method calculateAllLayerEfficiencies() whose purpose is to iterate over all layers in a network. Depending on the type of layer there is a switch statement and should call the correct calculateEfficiency() depending on the layer type.
class StrategyAssigner final {
public:
explicit StrategyAssigner(){};
public:
void calculateAllLayerEfficiencies() {
// Logic to iterate over all layers in
// a network
switch (layerType) {
case Convolution:
// Call calculateEfficiency() for Convolution
break;
case MaxPool:
// Call calculateEfficiency() for MaxPool
break;
}
};
}
int main ()
{
StrategyAssigner assigner;
assigner.calculateAllLayerEfficiencies();
}
My question is, should I store references of objects Convolution and MaxPool in the class StrategyAssigner so that I can call the respective calculateEfficiency().
Or could you suggest a better way to call calculateEfficiency(). I don't really know how to create the objects (stupid as that sounds).
I can't make calculateEfficiency() static as I need them to be virtual so that each derived class can implemented its own formula.
If you included complete code I could give a more detailed answer, but you need to store BaseStrategy pointers that are initialized with derived class instances. Here's an example made from some of your code:
std::vector<std::unique_ptr<BaseStrategy>> strategies;
strategies.emplace_back(new ConvolutionStrategy);
strategies.emplace_back(new MaxPoolStrategy);
for (int i = 0; i < strategies.size(); ++i) {
std::unique_ptr<BaseStrategy>& pStrat = strategies[i];
pStrat->calculateEfficiency(...);
}
Note that this won't compile because I don't have enough details from the code you posted to make it so, but this shows how to exploit polymorphism in the way that you need.
Also, I used smart pointers for memory management; use these at your discretion.
You can indeed use runtime polymorphism here:
Declare ~BaseStrategy virtual (you are already doing it ;-)
If you are never going to instantiate a BaseStrategy, declare one of its methods as virtual pure, e.g. calculateEfficiency (you are already doing it as well!). I would make that method const, since it doesn't look it's going to modify the instance. And it will need to be public, because it will need to be accessed from StrategyAnalyser.
Declare calculateEfficiency as virtual and override in each of the subclasses. It could also be final if you don't want subclasses to override it.
I'd keep a std::vector of smart pointers to BaseStrategy at StrategyAssigner. You can use unique_ptrs if you think this class is not going to be sharing those pointers.
The key point now is that you create heap instances of the subclasses and assign them to a pointer of the base class.
class StrategyAssigner final {
public:
void addStrategy(std::unique_ptr<BaseStrategy> s) {
strategies_.push_back(std::move(s));
}
private:
std::vector<std::unique_ptr<BaseStrategy>> strategies_{};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
}
Then, when you call calculateEfficiency using any of those pointers to BaseStrategy, the runtime polymorphism will kick in and it will be the method for the subclass the one that will be actually called.
class ConvolutionStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "ConvolutionStrategy::calculateEfficiency()\n";
return 10;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "MaxPoolStrategy::calculateEfficiency()\n";
return 20;
}
};
class StrategyAssigner final {
public:
void calculateAllLayerEfficiencies() {
auto sum = std::accumulate(std::cbegin(strategies_), std::cend(strategies_), 0,
[](auto total, const auto& strategy_up) {
return total + strategy_up->calculateEfficiency(); });
std::cout << "Sum of all efficiencies: " << sum << "\n";
};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
assigner.addStrategy(std::make_unique<MaxPoolStrategy>());
assigner.calculateAllLayerEfficiencies();
}
// Outputs:
//
// ConvolutionStrategy::calculateEfficiency()
// MaxPoolStrategy::calculateEfficiency()
// Sum of all efficiencies: 30
[Demo]
I have a base interface, declaration like this - IBaseTest.h:
#pragma once
template <class T1>
class IBaseTest
{
public:
virtual ~IBaseTest();
virtual T1 DoSomething() = 0;
};
And two children who overrides DoSomething() CBaseTest1 claass in - BaseTest1.h:
#pragma once
#include "IBaseTest.h"
class CBaseTest1: public IBaseTest<int>
{
public:
virtual int DoSomething();
};
BaseTest1.cpp:
#include "BaseTest1.h"
int CBaseTest1::DoSomething()
{
return -1;
}
And CBaseTest2 in - BaseTest2.h
#pragma once
#include "IBaseTest.h"
class CBaseTest2: public IBaseTest<long long>
{
public:
virtual long long DoSomething();
};
BaseTest2.cpp:
#include "BaseTest2.h"
long long CBaseTest2::DoSomething()
{
return -2;
}
So CBaseTest1::DoSomething() overrides return type to int, and CBaseTest2::DoSomething() to long long. Now, i want to use a pointer to the base interface, to work with those classes, and there i have the problem:
#include "IBaseTest.h"
#include "BaseTest1.h"
#include "BaseTest2.h"
int _tmain(int argc, _TCHAR* argv[])
{
IBaseTest<T1> * pBase = NULL;
pBase = new CBaseTest1();
cout << pBase->DoSomething() << endl;
pBase = new CBaseTest2();
cout << pBase->DoSomething() << endl;
getchar();
return 0;
}
The problem is i cannot declare IBaseTest<T1> * pBase = NULL; T1 is undefined. If declare the template before _tmain like this:
template <class T1>
int _tmain(int argc, _TCHAR* argv[])
{
...
}
I get: error C2988: unrecognizable template declaration/definition
So what do i put here instead of T1?
IBaseTest<??> * pBase = NULL;
The problem is that T1 parameter needs to be known when you instantiate an object of the template class IBaseTest. Technically, IBaseTest<int> and IBaseTest<long long> are two different types without a common base and C++ does not allow you to declare a variable IBaseTest<T1> pBase = NULL; where T1 is determined at runtime. What you are trying to achieve is something that would be possible in a dynamically typed language, but not in C++ because it is statically typed.
However, if you know the expected return type of DoSomething whenever you call that method, you can sort of make your example to work. First, you need to introduce a common base class that is not a template:
#include <typeinfo>
#include <typeindex>
#include <assert.h>
class IDynamicBase {
public:
virtual std::type_index type() const = 0;
virtual void doSomethingVoid(void* output) = 0;
template <typename T>
T doSomething() {
assert(type() == typeid(T));
T result;
doSomethingVoid(&result);
return result;
}
virtual ~IDynamicBase() {}
};
Note that it has a template method called doSomething that takes a type parameter for the return value. This is the method that we will call later.
Now, modify your previous IBaseTest to extend IDynamicBase:
template <class T1>
class IBaseTest : public IDynamicBase
{
public:
std::type_index type() const {return typeid(T1);}
void doSomethingVoid(void* output) {
*(reinterpret_cast<T1*>(output)) = DoSomething();
}
virtual T1 DoSomething() = 0;
virtual ~IBaseTest() {}
};
You don't need to change CBaseTest1 or CBaseTest2.
Finally, you can now write the code in your main function like this:
IDynamicBase* pBase = nullptr;
pBase = new CBaseTest1();
std::cout << pBase->doSomething<int>() << std::endl;
pBase = new CBaseTest2();
std::cout << pBase->doSomething<long long>() << std::endl;
Note that instead of calling pBase->DoSomething(), we now call pBase->doSomething<T>() where T is a type that must be known statically where we call the method and we provide that type at the call site, e.g. pBase->doSomething<int>().
The language does not allows to do directly what you are trying to do. At that point, you should ask yourself if that is the right solution for the problem.
The first approach that might work well assuming that you don't have too much different operations to do for each type would be to simply do the action in the function itself instead of returning type that are not related through inheritance.
class IBaseTest
{
public:
virtual void OutputTo(std::ostream &os) = 0;
};
class CBaseTest1
{
public:
virtual void OutputTo(std::ostream &os) override;
private:
int DoSomething();
};
void CBaseTest1OutputTo(std::ostream &os)
{
os << DoSomething() << std::endl;
}
If you have only a few types but a lot of operation, you might use the visitor pattern instead.
If you mainly have operation that depends on type, you could use:
class IVisitor
{
public:
virtual void Visit(int value) = 0;
virtual void Visit(long value) = 0;
};
Otherwise, use that which is more general
class IVisitor
{
public:
virtual void Visit (CBaseTest1 &test1) = 0;
virtual void Visit (CBaseTest2 &test2) = 0;
};
Then in your classes add an apply function
class IBaseTest
{
public:
virtual void Apply(IVisitor &visitor) = 0;
};
In each derived class, you implement the Apply function:
void CBaseTest1 : public IBaseTest
{
virtual void Apply(IVisitor &visitor) override
{
visitor.Visit(this->DoSomething()); // If you use first IVisitor definition
visitor.Visit(*this); // If you use second definition
};
And for creation purpose, you could have a factory that return the appropriate class from a type tag if you need to create those class from say a file…
One example assuming you want a new object each time:
enum class TypeTag { Integer = 1, LongInteger = 2 };
std::unique_ptr<IBaseTest> MakeObjectForTypeTag(TypeTag typeTag)
{
switch (typeTag)
{
case TypeTag::Integer : return new CBaseTest1();
case TypeTag::LongInteger : return new CBaseTest2();
}
}
So the only time you would do a switch statement is when you are creating an object… You could also use a map or even an array for that...
The right approach depends on your actual problem.
How many CBaseClass* do you have?
Do you expect to add other classes? Often?
How many operations similar to DoSomething() do you have?
How many actions that works on the result of DoSomething do you have?
Do you expect to add other actions? Often?
By responding to those questions, it will be much easier to take the right decision. If the action are stables (and you only have a few one), then specific virtual functions like OutputToabove is more appropriate. But if you have dozen of operation but don't expect much changes to ITestBase class hierarchy, then visitor solution is more appropriate.
And the reason why a given solution is more appropriate in a given context is mainly the maintenance effort when adding classes or actions in the future. You typically want that the most frequent change (adding a class or an action) require les changes everywhere in the code.
In the product I am working, one of very basic scenario is serialization of classes. Typically a class to be serialized calls serialization on its sub-component
e.g. if there is a class s.t. class
A{B;C;D;} then A.Pack will call pack
function on B,C,D.
Since there are many such classes, same pattern of code has to be duplicated over and over again.
Is it possible to encapsulate this behavior in a pattern (possibly using templates and inheritance)
The usual way of making a template do this is to use a type list:
#include <iostream>
// typelist definition
struct Empty {};
template < typename H, typename T = Empty >
struct Cons {
typedef H head;
typedef T tail;
};
// interfaces all items support
class IPack
{
public:
virtual void Pack() = 0;
};
// some packable items
class Fee : public IPack
{
public:
virtual void Pack() {
std::cout << "Packed Fee\n";
}
};
class Fi : public IPack
{
public:
virtual void Pack() {
std::cout << "Packed Fi\n";
}
};
class Fo : public IPack
{
public:
virtual void Pack() {
std::cout << "Packed Fo\n";
}
};
class Fum : public IPack
{
public:
virtual void Pack() {
std::cout << "Packed Fum\n";
}
};
// these two templates create a composite IPack from a list
// of the types of its parts
template <typename Types>
class PackList : public PackList<typename Types::tail>
{
protected:
typedef typename Types::head Item;
Item item;
public:
virtual void Pack() {
item.Pack();
PackList<typename Types::tail>::Pack();
}
};
template <>
class PackList<Empty> : public IPack
{
public:
virtual void Pack() {}
};
// FeeFiFoFum is a composite of four items
class FeeFiFoFum : public PackList<Cons<Fee,Cons<Fi,Cons<Fo,Cons<Fum> > > > >
{
};
// create a FeeFiFoFum and call pack on it, which calls pack on its parts
int main ()
{
FeeFiFoFum giant;
giant.Pack();
}
Proper implementations of composites created from type lists give you accessors for the members and so on, but this is enough to show how they works, and prints out that it packed Fee, Fi, Fo and Fum without specifying any behaviour.
One possible design that would help accomplish this is to use the Composite pattern. Your Component (to borrow from the Wikipedia drawing) is Packable, which would implement a Template Method Pack() that can do something like so:
GetChildren();
for each child:
child.Pack()
PackImpl();
PackImpl() is a pure virtual method in Packable, and all classes that inherit implement it appropriately. GetChildren() would return an STL container (possibly empty), for iteration. It can be implemented in Packable, along with a private member collection to store the child objects. Basically, you then inherit all the classes from Packable, implement PackImpl(), and you're done.
Note that this will cause issues if your inheritance hierarchy depends on the child pieces being members directly. If you've approached the problem in terms of aggregation, this should work well.
It's possible that the Visitor pattern may help.
http://en.wikipedia.org/wiki/Visitor_pattern
The idea of this is to separate the traversal logic (stepping through your objects) from the handling of each object. In this case, the per-object logic is serializing (encoding) a single object (or deserializing, of course). This should be fairly simple and minimally repetitive using normal OOP techniques.
Implementing the traversal and the Visitor-pattern specific code is annoying, but it's mostly boilerplate and should be a one-off thing.
One commenter wrote:
If you mean "is there a way I can write a template to automatically call a method on each of my member variables?", then the answer is no...
My (slightly evil) counter to that is yes, if the method is the destructor...
#include <iostream>
using namespace std;
bool Enable = false;
template <typename T>
class DS : public T {
public:
~DS() {
if (Enable) T::Serialize();
}
};
class A {
protected:
void Serialize() { cout << "A" << endl; }
};
class B {
protected:
void Serialize() { cout << "B" << endl; }
};
typedef DS<A> DSA;
typedef DS<B> DSB;
class C {
protected:
void Serialize() { cout << "C" << endl; }
private:
DSA a;
DSB b;
};
typedef DS<C> DSC;
int
main()
{
DSC c;
{
DSC c_copy = c;
Enable = true;
}
Enable = false;
}
The output is in reverse order, so to reconstruct objects you'd have to parse the serialized data and push each completed object on a stack. Composite objects would then know how many children to pop off of the stack. Or, of course, the serialization could go to an intermediate structure.
Another intriguing idea would be to use this hack once at startup (create and destroy only one special object) where the callbacks from the destructors would create a data structure that described the original object.
I also note that implicit copy constructors have potential for similar abuse, and possible in forward order...
I need several C++ classes to have a static method "register", however the implementation of register varies between those classes.
It should be static because my idea is to "register" all those classes with Lua (only once of course).
Obviously I can't declare an interface with a static pure virtual function. What do you guys suggest me to do ? Simplicity is welcome, but I think some kind of template could work.
Example of what I would like to achieve
class registerInterface
{
public:
static virtual void register() = 0; //obviously illegal
};
class someClass: public registerInterface
{
static virtual void register()
{
//I register myself with Lua
}
}
class someOtherClass: public registerInterface
{
static virtual void register()
{
//I register myself with Lua in a different way
}
}
int main()
{
someClass::register();
someOtherClass::register();
return 0;
}
Based on how you've described the problem, it's unclear to me why you even need the 'virtual static method' on the classes. This should be perfectly legal.
class SomeClass {
static void register(void) {
...
}
}
class SomeOtherClass {
static void register(void) {
...
}
}
int main(int argc, char* argv[]) {
SomeClass::register();
SomeOtherClass::register();
return 0;
}
Drop the RegisterInterface, I don't think you need it.
If it helps, you could take Hitesh's answer, and add:
struct luaRegisterManager {
template <typename T>
void registrate() {
T::registrate();
// do something else to record the fact that we've registered -
// perhaps "registrate" should be returning some object to help with that
}
};
Then:
int main() {
luaRegisterManager lrm;
lrm.registrate<someClass>();
lrm.registrate<someOtherClass>();
}
More generally, if you want to introduce any dynamic polymorphism in C++, then you need an object, not just a class. So again, perhaps the various register functions should be returning objects, with some common interface base class registeredClass, or classRegistrationInfo, or something along those lines.
Could provide an example of what you feel it is that you need dynamic polymorphism for? Hitesh's code precisely matches your one example, as far as I can see, so that example must not cover all of your anticipated use cases. If you write the code that would be using it, perhaps it will become clear to you how to implement it, or perhaps someone can advise.
Something else that might help:
#include <iostream>
#include <string>
#include <vector>
struct Registered {
virtual std::string name() = 0;
virtual ~Registered() {}
Registered() {
all.push_back(this);
}
static std::vector<Registered*> all;
};
std::vector<Registered*> Registered::all;
typedef std::vector<Registered*>::iterator Iter;
template <typename T>
struct RegisteredT : Registered {
std::string n;
RegisteredT(const std::string &name) : n(name) { T::registrate(); }
std::string name() { return n; }
// other functions here could be implemented in terms of calls to static
// functions of T.
};
struct someClass {
static Registered *r;
static void registrate() { std::cout << "registering someClass\n"; }
};
Registered *someClass::r = new RegisteredT<someClass>("someClass");
struct someOtherClass {
static Registered *r;
static void registrate() { std::cout << "registering someOtherClass\n"; }
};
Registered *someOtherClass::r = new RegisteredT<someOtherClass>("someOtherClass");
int main() {
for (Iter it = Registered::all.begin(); it < Registered::all.end(); ++it) {
std::cout << (*it)->name() << "\n";
}
}
There are all sorts of problems with this code if you try to split it across multiple compilation units. Furthermore, this kind of thing leads to spurious reports from memory leak detectors unless you also write some code to tear everything down at the end, or use a vector of shared_ptr, Boost pointer vector, etc. But you see the general idea that a class can "register itself", and that you need an object to make virtual calls.
In C++ you usually try to avoid static initialisation, though, in favour of some sort of setup / dependency injection at the start of your program. So normally you would just list all the classes you care about (calling a function on each one) rather than try to do this automatically.
Your intentions are noble, but your solution is inkling towards "overengineering" (unless I am missing an obvious solution).
Here is one possibility: You can use the Virtual Friend function idiom For example,
class RegisterInterface{
friend void register(RegisterInterface* x){x->do_real_register();}
protected:
virtual void do_real_register();
}
class Foo : public RegisterInterface{
protected:
virtual void do_real_register(){}
};
class Bar : public RegisterInterface{
protected:
virtual void do_real_register(){}
};
int main(int argc, char* argv[]) {
BOOST_FOREACH(RegisterInterface* ri, registered_interfaces)
{
register(ri);
}
return 0;
}
I know you've already accepted an answer, but I figured I would write this up anyway. You can have self-registering classes if you use some static initialization and the CRTP:
#include <vector>
#include <iostream>
using namespace std;
class RegisterableRoot // Holds the list of functions to call, doesn't actually need
// need to be a class, could just be a collection of globals
{
public:
typedef void (*registration_func)();
protected:
static std::vector<registration_func> s_registery;
public:
static void do_registration()
{
for(int i = 0; i < s_registery.size(); ++i)
s_registery[i]();
}
static bool add_func(registration_func func) // returns something so we can use it in
// in an initializer
{
s_registery.push_back(func);
return true;
}
};
template<typename RegisterableType> // Doesn't really need to inherit from
class Registerable : public RegisterableRoot // RegisterableRoot
{
protected:
static const bool s_effect;
};
class A : public Registerable<A> // Honestly, neither does A need to inherit from
// Registerable<T>
{
public:
static void Register()
{
cout << "A" << endl;
}
};
class B : public Registerable<B>
{
public:
static void Register()
{
cout << "B" << endl;
}
};
int main()
{
RegisterableRoot::do_registration();
return 0;
}
std::vector<RegisterableRoot::registration_func> RegisterableRoot::s_registery;
template <typename RegisterableType> // This is the "cute" part, we initialize the
// static s_effect so we build the list "magically"
const bool Registerable<RegisterableType>::s_effect = add_func(&RegisterableType::Register);
template class Registerable<A>; // Explicitly instantiate the template
// causes the equivalent of
// s_registery.push_back(&A::Register) to
// be executed
template class Registerable<B>;
This outputs
A
B
although I wouldn't rely on this order if I were you. Note that the template class Registerable<X> need not be in the same translation unit as the call to do_registration, you can put it with the rest of your definition of Foo. If you inherit from Registerable<> and you don't write a static void Register() function for your class you'll get a (admittedly probably cryptic) compiler error much like you might expect if there really was such a thing as "static virtuals". The "magic" merely adds the class specific function to the list to be called, this avoids several of the pitfalls of doing the actual registration in a static initializer. You still have to call do_registration for anything to happen.
How about this way? Define an interface class:
// IFoobar.h
class IFoobar{
public:
virtual void Register(void) = 0;
}
Then define the class that handles the register..
// RegisterFoobar.h
class RegisterFoobar{
public:
// Constructors etc...
IFoobar* fooBar;
static void RegisterFoobar(IFoobar& fubar){
foobar = &fubar;
}
private:
void Raise(void){ foobar->Register(); }
}
Now, then define another class like this
// MyFuBar.h
class MyFuBar : IFoobar{
public:
// Constructors etc...
void Register(void);
private:
RegisterFoobar* _regFoobar;
}
Call the code like this:
//MyFuBar.cpp
MyFuBar::MyFuBar(){
_regFoobar = new Foobar();
_regFoobar->RegisterFoobar(this);
}
void MyFuBar::Register(void){
// Raised here...
}
Maybe I have misunderstood your requirements...
A while back I learned about the Curiously Recurring Template Pattern (http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern), and it reminded me of a technique I had used to implement an event queue cache.
The basic idea is that we take advantage of a Base class pointer to store a container of homogeneous pointer types. However because the Derived class is a template class, which stores an item of type T, what we are really storing is a list of heterogeneous types.
I was curious if anyone has seen this technique, which is perhaps interesting, and if so if anyone has named it? Anyone care to critique it? Is there a better way to achieve my end here?
Thanks.
#include <iostream>
#include <algorithm>
#include <functional>
#include <list>
#include <string>
class Base
{
public:
Base(){}
virtual ~Base(){}
virtual void operator()() = 0;
};
template<typename C, typename T>
class Derived : public Base
{
public:
Derived(C* c, T item) : consumer_(c), item_(item) {}
virtual void operator()()
{
consumer_->consume(item_);
}
C* consumer_;
T item_;
};
class Consumer
{
bool postpone_;
std::list<Base*> cache_;
public:
Consumer() : postpone_(true)
{
}
void pause()
{
postpone_ = true;
}
void resume()
{
postpone_ = false;
const std::list<Base*>::iterator end = cache_.end();
for ( std::list<Base*>::iterator iter = cache_.begin();
iter != end;
++iter )
{
Base* bPtr = *iter;
bPtr->operator()();
delete bPtr;
}
cache_.clear();
}
void consume(int i)
{
if ( postpone_ )
{
std::cerr << "Postpone int.\n";
cache_.push_back(new Derived<Consumer, int>(this, i));
}
else
{
std::cerr << "Got int.\n";
}
}
void consume(double d)
{
if ( postpone_ )
{
std::cerr << "Postpone double.\n";
cache_.push_back(new Derived<Consumer, double>(this, d));
}
else
{
std::cerr << "Got double.\n";
}
}
void consume(char c)
{
if ( postpone_ )
{
std::cerr << "Postpone char.\n";
cache_.push_back(new Derived<Consumer, char>(this, c));
}
else
{
std::cerr << "Got char.\n";
}
}
};
static Consumer consumer;
void destroy(Base* object)
{
delete object;
}
int main()
{
// Consumer is registered with something that sends events out to lots
// of different consumer types (think observer pattern). Also in the non-toy
// version consumer isn't being passed PODs, but various Event types.
consumer.consume(0);
consumer.consume(0.1f);
consumer.consume('x');
consumer.resume();
}
The output is:
Postpone int.
Postpone double.
Postpone char.
Got int.
Got double.
Got char.
What you are using is plain polymorphism, as Stephen points out in his comment. While you store different objects internally in the container, you are limited to using the interface defined in Base. That is, of course, unless you intend to add type checking and downcasts to actually retrieve the values. There is just a limited amount of things that you can do with unrelated objects.
Depending on what you are actually wanting to achieve you might consider using other solutions like boost::any/boost::variant if what you want is to actually store unrelated types (in the few cases where this makes sense --cells in a spreadsheet, for example).
anyone has named it?
I think it is an adapter pattern implemented without using inheritance from T.
Anyone care to critique it?
YOu could have used short template function instead of this class. Or you could use template function that returns template class. Template function can automatically guess required types - sou you could omit <> and do less typing.
Nice.
You're utilizing compiler's power to generate templated series of derived classes and it's actually cool that you can mix plain derived classes
(written by yourself) with template-specialized derived classes and with compiler-generated ones
(built as result of template instantiation).
class Base { ... };
template <typename Y> class Derived1 : public Base { ... };
template <specialization>
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
This could be useful, but it doesn't somehow extend the polymorphism term, because you're still limited to the Base class interface.
Also, you could write a plain factory which would have some templated method for generating subclasses and use it to avoid writing new Derived1<std::string>..., but write something like
std::string a;
Base* base = Factory.Create(a)