I have a parent class "Parent" which requires a template parameter K for the data type it operates on. For the child implementations, I'd like to force these to implement a custom "deepcopy" method.
An example use of the deepcopy method is given by the "Runner" class, which essentially holds a master copy of a given Child implementation. Note that in a real-world example, the Runner type would have multiple threads accessing and mutating the "master" field simultaneously while holding a lock, hence the need for deep-copies of the master type.
I've currently solved this as follows:
#include <iostream>
#include <vector>
template<typename T, typename K>
class Parent{
public:
virtual void mutate_state(std::vector<K> &data)=0;
T deepcopy(){
T res;
res = static_cast<T&>(*this);
return res;
}
};
// some example implementation of Base<T, K>
class Child : public Parent<Child, int>{
private:
std::vector<int> all_elements;
int state;
public:
void mutate_state(std::vector<int> &data) override{
// do something with data & cfg
all_elements.insert(all_elements.end(), data.begin(), data.end());
state++;
std::cout<<"Called A, state is: "<<state<<std::endl;
}
Child(Child &child) {
std::cout<<"call custom child copy constructor"<<std::endl;
state = child.state;
}
Child& operator=(Child other)
{
std::cout<<"call custom child copy assignment"<<std::endl;
std::swap(state, other.state);
return *this;
}
Child(): state(0){};
};
// an example class mutating the Child
template<typename T, typename K>
class Runner {
private:
// master Child instance
T master;
public:
explicit Runner(T child_impl) : master(child_impl) {}
T get_master_deepcopy() {
return master.deepcopy();
}
void update_master_model(T new_master) {
master = new_master;
}
void update(std::vector<int> &data){
T temp_deepcopy = get_master_deepcopy();
temp_deepcopy.mutate_state(data);
master = temp_deepcopy;
}
};
int main() {
Child base_impl;
// not nice: I have to keep specifying template type K=int although its already been defined in the child implementation
Runner<Child, int> runner(base_impl);
std::vector<int> some_data;
runner.update(some_data);
}
However, my implementation feels cumbersome.
There is currently no mechanism to "force" an implementation of custom copy operators in a child implementation. If they are forgotten, a child implementation which uses complex dynamically allocated types may only lead to shallow copy which I want to strictly avoid.
My Runner is unaware of the true type of T which should be restricted to inherit from the class Parent<T, K>
Also, I dislike the need to repeatedly declare the type of template parameter K
both in the implementation of Child as well when instantiating the "Runner" type. Is there a way to extract the template type K from the already defined Child class when instantiating the "Runner" type?
How can I improve this approach?
Related
I have a C++ class which is essentially a container:
class SimpleContainer {
public:
// Various accessor methods / iterators
private:
// The actual content
}
In addition to the SimpleContainer - I want to create a StrictContainer which extends SimpleContainer semantically by enforcing rules on the content, but using the same content as an existing SimpleContainerinstance.
class StrictContainer : public SimpleContainer {
StrictContainer( const SimpleContainer& simple ) {
// Check content in simple, and raise an exception
// if it is not valid.
}
}
Now - my problem is what kind of relationship there should be between the SimpleContainer and the StrictContainer:
is-a:
seems natural; and that is what I have indicated with the inheritance, but then I will create a StrictContainer instance based on extending SimpleContainer instance post construction - is that possible?
has-a
Alternatively I could implement it as a has-a relationship where the StrictContainer has a SimpleContainer member, but then I would need to implement all the accessors and iterators again in the StrictContainer and forward to the SimpleContainer implementation.
The container is quite large; and I would really not copy the content when creating the StrictContainer. I guess what I would like was a way to implement my own downcast operator:
SimpleContainer simple;
// Fill simpleContainer
{
StrictContainer* strict = downcast<StrictContainer>( simple )
...
}
Where the downcast<StrictContainer> would call a method on the StrictContainer to verify the content of the simple input argument?
is-a would be a disaster. Assume the rule is that SimpleContainer contains integers, and StrictContainer only contains odd integers.
StrictContainer strict;
SimpleContainer simple;
strict.insert(1); // OK value is odd
simple.insert(2); // OK simple doesn't check oddness.
SimpleContainer& sc = strict; // Reference to base.
sc.SimpleContainer::insert(2); // Uh-oh. That will use the simple container version
// of insert (even in the presence of virtual functions)
// and will insert an invalid even number into `simple`.
You need has-a
As a third option, I'd suggest a policy based approach as in the following example:
#include<vector>
#include<cassert>
template<typename T>
struct NoCheck {
static bool isOk(T) {
return true;
}
};
template<typename T>
struct TheAnswer {
static bool isOk(T t) {
return false;
}
};
template<>
struct TheAnswer<int> {
static bool isOk(int t) {
return t == 42;
}
};
template<typename T, template<typename> class C = NoCheck>
struct SimpleContainer {
bool add(T t) {
if(C<T>::isOk(t)) {
vec.push_back(t);
return true;
}
return false;
}
private:
std::vector<T> vec{};
};
int main() {
SimpleContainer<int> c1;
assert(c1.add(42));
assert(c1.add(0));
SimpleContainer<int, TheAnswer> c2;
assert(c2.add(42));
assert(not c2.add(0));
}
If having a common interface is a requirement (it's not clear from the question), you can get it with a factory method and a type-erased internal class still based on a policy.
So, restating your requirements:
The StrictContainer has the same interface as the SimpleContainer,
with additions. (This implies an is-a relationship to the
interface.)
Intstantiating a new StrictContainer should not require
copying the SimpleContainer content. (This implies decomposition using a handle.)
Assuming that the lifetime of the original SimpleContainer spans the StrictContainer, this sounds like the decorator pattern. So, if you're willing to do a bit of decomposition -- how about defining an interface like this?
class MyInterface {
// No contained state needed at all.
public:
virtual ~MyInterface() {}
virtual bool getThing1() const = 0;
virtual int getThing2() const = 0;
// and so on...
};
class MyDecorator : public MyInterface {
MyInterface &m_impl; // Could use a smart pointer, if available.
public:
MyDecorator( MyInterface &impl ): m_impl(impl) {}
bool getThing1() const override { return impl.getThing1(); }
int getThing2() const override { return impl.getThing2(); }
// and so on...
};
Then your concrete implementation:
class SimpleContainer : public MyInterface {
bool m_thing1;
int m_thing2;
... // All the real state goes here.
public:
... // All the interface methods go here.
};
Then, the StrictContainer is a lightweight container that retains a handle to the original SimpleContainer, instead of a full copy.
class StrictContainer : public MyDecorator {
// Additional state, if needed.
public:
StrictContainer( SimpleContainer &base ): MyDecorator(base) {}
// Additional methods (like your additional validation method.
};
There's no need for a special "downcast operator", since you already need to call the constructor for StrictContainer and it already does everything you need.
SimpleContainer simple( ... ); // Construct as normal.
StrictContainer strict = simple; // Assuming no extra arguments needed.
Pretty simple.
And yes, you need to write the delegation operations for each method in the interface once in the decorator class. But you could define multiple variants of the StrictContainer class without having to implement them again (unless you want to override some of them).
I prefer implementing something like this using a combination of Adapter and Strategy (Policy) pattern. You can decouple the StrictContainer (which is the adapter) from the underlying container holding the data entirely. Very similar to how std::queue is implemented as an adapter to another container (like vector). You can then parameterize the StrictContainer-adapter with whatever constraints you want to. Whenever you add an element to your container, it is checked whether the constraint is satisfied. If it is, the element is added to the underlying container, otherwise you can do whatever you prefer to (leave the container unchanged or throw an exception for instance).
template<typename T, typename Container, typename Constraint>
class StrictContainer
{
public:
StrictContainer(const Container& container = {}, Constraint constraint = {})
: container_(container), constraint_(constraint)
{
validateAll();
}
StrictContainer(Container&& container, Constraint constraint = {})
: container_(std::move(container)), constraint_(constraint)
{
validateAll();
}
// container interface ...
void push_back(const T& value)
{
if(!constraint_(value))
throw WhateverException();
container_.push_back(value);
}
private:
void validateAll()
{
for(const auto& value : container_)
{
if(!constraint_(value))
throw WhateverException();
}
}
Container container_;
Constraint constraint_;
};
You can then instantiate the StrictContainer like this:
StrictContainer<int, std::vector<int>, IsEvenConstraint<int>> myContainer;
myContainer.push_back(2);
myContainer.push_back(18);
myContainer.push_back(7); // throws
In this case the StrictContainer uses a std::vector as data store, but you could use whatever container you prefer (like your SimpleContainer). The constraints can then be implemented like this
template<typename T>
struct IsEvenConstraint
{
bool operator()(const T& value)
{
return value % 2 == 0;
}
};
Depending on the classes of containers and constraints you like to support you might have to adjust the interface accordingly. Using variadic templates you can extend the StrictContainer to support multiple constraints. You can use a lambda for the constraint as well.
auto lessThanOne = [](float f) { return f < 1.0f; };
StrictContainer<float, std::vector<float>, decltype(lessThanOne)> myContainer2(std::vector<float>{}, lessThanOne);
myContainer2.push_back(0.1f);
myContainer2.push_back(1.7f); // throws
I'll get straight to it: I have a class template that holds a reference and updates info to it:
template<class T>
class Parser {
T& m_ref;
public:
typedef T ValueType;
Parser(T& ref): m_ref(ref) {}
virtual void read(std::istream&);
};
Now, I have another template that creates a new object and updates it using this interface, to do so I have a field that saves the parser.
However, I'd like to use updater to classes that derive from T, which is impossible with poymorphism since Parser<Derived> does not inherit from Parser<Base>.
I created this work-around that uses an intermediate class that inherits from Parser<Base> but updates into a Parser<Derived>:
template<class T>
struct dummy {};
template<class T>
class Creator {
typedef shared_ptr<Parser<T> > ParserPtr;
typedef shared_ptr<T> ValuePtr;
ValuePtr m_output;
ParserPtr m_parser;
template<class ParserType>
class LocalParser : public Parser<T> {
ParserType m_parser;
public:
LocalParser(typename ParserType::ValueType& val):
Parser<T>(/*???*/), //problems start here, I must initialize the base
m_parser(val) {}
void read(std::istream& is) { //use polymorphism to update into some derieved reference
m_parser.read(is);
}
};
public:
Creator(): //Uses Parser<T> as default parser
m_output(new T),
m_parser(new Parser<T>(*m_output)) {}
template<class ParserType>
Creator(dummy<ParserType>) { //Use any parser
auto temp = make_shared(new typename ParserType::ValueType);
m_output = temp;
m_parser = maked_shared(new LocalParser<ParserType>(*temp));
}
virtual ValuePtr read()(std::istream& is) {
m_parser->read(is);
return m_output;
}
};
Basically LocalParser is an intermediate class that inherits from Parser<T> but updates a diffrent reference from the one it's base holds.
The problem here is how to initialize Parser<T>, especially when T is abstract (which is 99% of the time I actually use this class with a derived parser).
My question boils down to "how to define a reference to a (possibly) abstract class that WON'T be used?" (or is there any kind of other work around where I don't define an intermidiate that inherits from Parser<T>).
EDIT: The Parser interface is a separate code I cannot change.
You cannot create an empty reference. A reference must refer to something. That's one of the key differences between a reference and a pointer. In fact, there's a possible solution for you:
T& ref; // error
T& ref = nullref; // no such thing
T* ptr = nullptr; // "empty" pointer!
Another possibly more explicit solution that allows for either a reference or nothing would be to use boost::optional:
boost::optional<T&> opt_ref; // empty optional
opt_ref = some_t;
What is the most elegant way to provide an interface in C++ that accepts derived class types that carry with them different data type members that then need to be retrieved later. The example below illustrates this where the Container class provides methods to "post" an Item that will be some kind of derived variant of BaseItem. Later on I want to get the derived Item back and extract its value.
The main thing I want is for the Container interface (post and receive) to stay the same in the future while allowing different "Item" derived types to be defined and "passed" through it. Would template be better for this somehow; I'd rather not use RTTI. Maybe there is some simple, elegant answer to this, but right now I'm struggling to think of it.
class ItemBase {
// common methods
};
class ItemInt : public ItemBase
{
private:
int dat;
public:
int get() { return dat; }
};
class ItemDouble : public ItemBase
{
private:
double dat;
public:
double get() { return dat; }
};
class Container {
public:
void post(int postHandle, ItemBase *e);
ItemBase* receive(int handle); // Returns the associated Item
};
int main()
{
ItemInt *ii = new IntItem(5);
Container c;
c.post(1, ii);
ItemInt *jj = c.receive(1);
int val = jj->get(); // want the value 5 out of the IntItem
}
This is definitely a candidate for generic programming, rather than inheritance. Remember, generics (templates) are ideal when you want identical handling for different data types. Your ItemInt and ItemDouble classes violate OO design principles (the get() method returns different data types depending on what the actual subtype is). Generic programming is built for that. The only other answer would be a tagged data type, and I personally avoid those like the plague.
How about?
template<typename T>
class Item
{
private:
T dat;
public:
T get() { return dat; }
};
class Container {
public:
template<typename T>
void post(int postHandle, Item<T> *e);
template<typename T>
Item<T>* receive(int handle); // Returns the associated Item
};
int main()
{
Item<int> *ii = new Item<int>(5);
Container c;
c.post(1, ii);
Item<int> *jj = c.receive<int>(1);
int val = jj->get(); // want the value 5 out of the IntItem
}
Your Container class looks suspiciously like a std::map. It looks to me like your ItemBase class is just a different name for "Object", the universal base class, which I think is not much different from (or better than) void*. I would avoid trying to contain items of different type in a single container. If your design seems to call for doing so, I'd rethink your design.
A pure template approach doesn't work because you apparently want to have mixed types in your container. You could work with something like Boost's any although I think you need to restore the actual. What I think is called for in this case is a base class exposing the type-independent and virtual methods plus a templatized derived class to hold the actual items:
class Base {
public:
virtual ~Base() {}
virtual void post() = 0;
};
template <typename T>
class Item: public Base {
public:
Item(T const& value): value_(value) {}
void post() { std::cout << "posting " << this->value_ << "\n"; }
private:
T value_;
};
This approach avoids the need to write any derived Item class for another value type. To make creation of these beast easier you probably want to create a suitable creation function as well, e.g.
template <typename T>
std::unique_ptr<Base> make_item(T const& value) {
return std::unique_ptr<Base>(new Item<T>(value));
}
A std::unique_ptr<Base> is returned to make sure that the allocated object is released (if you don't use C++2011 you can used std::auto_ptr<T> instead). This type can easily be converted to other pointer types, e.g. to a std::shared_ptr<Base> which is a better suited to be put into a container.
What are the ways in C++ to handle a class that has ownership of an instance of another class, where that instance could potentially be of a number of classes all of which inherit from a common class?
Example:
class Item { //the common ancestor, which is never used directly
public:
int size;
}
class ItemWidget: public Item { //possible class 1
public:
int height;
int width;
}
class ItemText: public Item { //possible class 2
std::string text;
}
Let's say there is also a class Container, each of which contains a single Item, and the only time anyone is ever interested in an Item is when they are getting it out of the Container. Let's also say Items are only created at the same time the Container is created, for the purpose of putting them in the Container.
What are the different ways to structure this? We could make a pointer in Container for the contained Item, and then pass arguments to the constructor of Container for what sort of Item to call new on, and this will stick the Items all in the heap. Is there a way to store the Item in the stack with the Container, and would this have any advantages?
Does it make a difference if the Container and Items are immutable, and we know everything about them at the moment of creation, and will never change them?
A correct solution looks like:
class Container {
public:
/* ctor, accessors */
private:
std::unique_ptr<Item> item;
};
If you have an old compiler, you can use std::auto_ptr instead.
The smart pointer ensures strict ownership of the item by the container. (You could as well make it a plain pointer and roll up your own destructor/assignment op/copy ctor/move ctor/ move assignment op/ etc, but unique_ptr has it all already done, so...)
Why do you need to use a pointer here, not just a plain composition?
Because if you compose, then you must know the exact class which is going to be composed. You can't introduce polymorphism. Also the size of all Container objects must be the same, and the size of Item's derived classes may vary.
And if you desperately need to compose?
Then you need as many variants of Container as there are the items stored, since every such Container will be of different size, so it's a different class. Your best shot is:
struct IContainer {
virtual Item& getItem() = 0;
};
template<typename ItemType>
struct Container : IContainer {
virtual Item& getItem() {
return m_item;
}
private:
ItemType m_item;
};
OK, crazy idea. Don't use this:
class AutoContainer
{
char buf[CRAZY_VALUE];
Base * p;
public:
template <typename T> AutoContainer(const T & x)
: p(::new (buf) T(x))
{
static_assert(std::is_base_of<Base, T>::value, "Invalid use of AutoContainer");
static_assert(sizeof(T) <= CRAZY_VAL, "Not enough memory for derived class.");
#ifdef __GNUC__
static_assert(__has_virtual_destructor(Base), "Base must have virtual destructor!");
#endif
}
~AutoContainer() { p->~Base(); }
Base & get() { return *p; }
const Base & get() const { return *p; }
};
The container requires no dynamic allocation itself, you must only ensure that CRAZY_VALUE is big enough to hold any derived class.
the example code below compiles and shows how to do something similar to what you want to do. this is what in java would be called interfaces. see that you need at least some similarity in the classes (a common function name in this case). The virtual keyword means that all subclasses need to implement this function and whenever that function is called the function of the real class is actually called.
whether the classes are const or not doesn't harm here. but in general you should be as const correct as possible. because the compiler can generate better code if it knows what will not be changed.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class outputter {
public:
virtual void print() = 0;
};
class foo : public outputter {
public:
virtual void print() { std::cout << "foo\n"; }
};
class bar : public outputter {
public:
virtual void print() { std::cout << "bar\n"; }
};
int main(){
std::vector<outputter *> vec;
foo *f = new foo;
vec.push_back(f);
bar *b = new bar ;
vec.push_back(b);
for ( std::vector<outputter *>::iterator i =
vec.begin(); i != vec.end(); ++i )
{
(*i)->print();
}
return 0;
}
Output:
foo
bar
Hold a pointer (preferably a smart one) in the container class, and call a pure virtual clone() member function on the Item class that is implemented by the derived classes when you need to copy. You can do this in a completely generic way, thus:
class Item {
// ...
private:
virtual Item* clone() const = 0;
friend Container; // Or make clone() public.
};
template <class I>
class ItemCloneMixin : public Item {
private:
I* clone() const { return new I(static_cast<const I&>(*this); }
};
class ItemWidget : public ItemCloneMixin<ItemWidget> { /* ... */ };
class ItemText : public ItemCloneMixin<ItemText> { /* ... */ };
Regarding stack storage, you can use an overloaded new that calls alloca(), but do so at your peril. It will only work if the compiler inlines your special new operator, which you can't force it to do (except with non-portable compiler pragmas). My advice is that it just isn't worth the aggravation; runtime polymorphism belongs on the heap.
suppose you have two (or more) classes with private member vectors:
class A {
private:
std::vector<X> priv_vec;
public:
//more stuff
}
class B {
private:
std::vector<Y> priv_vec;
public:
//more stuff
}
and you have a functor-class which has a state and works on a generic vector (does sorting or counts elements or something like that). The state of the functor is initialized by the first vector the functor is working on. If the functor is applied to another vector later, it will change its behavior depending on the state (sorts in the same way or trims the second vector after as many elements as the first one, etc)
What is the best way to implement such a functor (desgin-pattern or functional interface?) without exposing the private vectors to the other classes or the user of the classes?
for example:
The user would like to initialize this functor with an object of class A and then use this initialized functor for one or more objects of class B. The user isn't able (and shouldn't be) to use the private vectors directly as function-arguments for the functor.
Hum, first, beware on states in functors.
Most STL implementation of the algorithms may copy your functors around, therefore you generally have to extract the state in an outer structure.
Now, for the application of functors, well it is simple: have your classes declare a template member function!
class A
{
public:
template <class Functor>
Functor Apply(Functor f);
private:
};
class B
{
public:
template <class Functor>
Functor Apply(Functor f);
};
// Usage
MyFunctor f;
A a;
B b;
b.Apply(a.Apply(f));
As for the functor, if you need state:
// Alternative 1
class FunctorState {};
class Functor
{
public:
Functor(FunctorState& state): m_state(state) {}
// some operator()(...)
private:
FunctorState& m_state;
};
// Alternative 2
class Functor
{
struct FunctorState {};
public:
Functor(): m_state(new FunctorState) {}
// some operator()(...)
private:
boost::shared_ptr<FunctorState> m_state;
};
This way, copies of the Functor all points to the same FunctorState instance. Just choose depending if you wish to actually access the state from outside the class or not.
Looks like a problem of importing policies from an object of class A and applying them to objects of class B, the only difference being, all of this is done at runtime (as opposed to typical policy-based design). This begs the question, are these policies proprietary to class A or can we isolate them and pass them around as required? That ought to simplify the deisgn.
A solution based on templates.
#include <iostream>
#include <string>
#include <vector>
// Wraps up a vector of type T and exposes a
// simple interface to access it.
template <class T>
class A
{
public:
A(const std::vector<T>& v) : priv_vec(v) { }
virtual size_t count() const { return priv_vec.size(); }
virtual T operator[](size_t index) const { return priv_vec[index]; }
private:
std::vector<T> priv_vec;
};
// A sample functor with state.
// The state is the size and current index of the vector object.
class Functor
{
public:
Functor() : _size(0), _index(0) { }
// Prints the element at the current index.
// If the index exceeds size, it is reset to 0.
template <class T>
void operator()(const A<T>& b)
{
if (_size == 0) _size = b.count();
if (_index >= _size) _index = 0;
std::cout << b[_index++] << '\n';
}
private:
size_t _size;
size_t _index;
};
int
main()
{
// Some tests.
std::vector<int> int_vec;
int_vec.push_back(1);
int_vec.push_back(2);
int_vec.push_back(3);
A<int> a(int_vec);
std::vector<std::string> str_vec;
str_vec.push_back("aaaa");
str_vec.push_back("bbbb");
str_vec.push_back("cccc");
A<std::string> b(str_vec);
Functor f;
f(a); // 1
f(b); // bbbb
f(a); // 3
f(a); // 1
f(a); // 2
f(b); // cccc
return 0;
}