C++ Value semantics, Immutablity and Inheritance - c++

Shared pointer to an immutable type has value semantics
I am trying to create a builder class which has value semantics which looks like something like this
class Pipeline {
public:
Pipeline(
const std::string& name,
std::optional<size_t> limitIn,
std::optional<size_t> limitOut) {...}
shared_ptr<const Pipeline> limitInput(size limit) const {
return make_shared<Pipeline>(name_, size_, limit, limitOut_) ;
}
shared_ptr<const Pipeline> limitOutput(size limit) const {
return make_shared<Pipeline>(name_, size_, limitInput_, limit) ;
}
private:
const string name_;
const size_t limitInput_;
const size_t limitOutput_;
};
Since member variables are const, shared_ptr is essentially immutable.
However this pattern breaks down when I need to add inheritance. For ex:
class Pipeline {
...
virtual void doSomething() const = 0;
}
Now in any of the methods (say in limitOutput) when I need to create a new instance of Pipeline I would need to know about the derived class as well since I cannot create an instance of Pipeline anymore. One way I can think of to solve this is to add another virtual method to initialize the object.
class Pipeline {
...
virtual shared_ptr<Pipeline> create(const std::string& name,
std::optional<size_t> limitIn,
std::optional<size_t> limitOut) const = 0;
}
class SpecialPipeline : public Pipeline {
...
virtual shared_ptr<Pipeline> create(const std::string& name,
std::optional<size_t> limitIn,
std::optional<size_t> limitOut) const override {
return make_shared<SpecialPipeline>(name, limitIn, limitOut);
}
};
Now all methods would just defer to this
shared_ptr<const Pipeline> limitInput(size limit) const {
return create(name_, size_, limit, limitOut_);
}
While this works I personally feel it isn't elegant, involves duplication construction and doesn't feel idiomatic. How would one go about implementing this ? Any feedback would be appreciated.

The simplest way to deal with this problem is:
Don't expose the constructor; make it protected.
Provide factory members on the base type and derived types that return std::unique_ptr<const T> or std::shared_ptr<const T>.
Remove the const qualification on your data members.
Add a virtual clone method that makes a copy and returns std::unique_ptr<Pipeline>.
From the outside, there is no way to obtain a non-const object since the constructor is not public, so the members do not need to be const.
Since the members are not const, your mutation-factory methods can:
Invoke the clone method to make a copy.
Mutate the data member on the copy.
Extract the pointer from the std::unique_ptr and return a new smart pointer with a const target.

I would use the Curiously Recurring Template Pattern here:
template <class T>
class Pipeline {
public:
Pipeline(
const std::string& name,
std::optional<size_t> limitIn,
std::optional<size_t> limitOut) {...}
shared_ptr<const T> limitInput(size limit) const {
return make_shared<T>(name_, limit, limitOut_) ;
}
shared_ptr<const T> limitOutput(size limit) const {
return make_shared<T>(name_, limitInput_, limit) ;
}
...
};
And in child classes:
class Child: public Pipeline<Child> {
public:
Child(
const std::string& name,
std::optional<size_t> limitIn,
std::optional<size_t> limitOut): Pipeline<Child>(name, limitIn, limitOut) {}
...
];
That way the child classes have only to have a constructor with the same parameters as their parent and delegate to this one.

Related

Pattern for removing default constructor which leaves data in "bad state"?

Let's say you have a class which have members which should always be set (i.e. defaults would leave it in a bad state). To prevent having objects with "bad state", you have a constructor which requires everything to be set. The issue is, that you also have a set of "factory" classes, create the objects by parsing some data stream and setting members directly. You want to be explicit about which classes can construct your objects without using the constructor. Is there a good pattern for this?
Example:
enum class DataState
{
STATE_ONE,
STATE_TWO
};
class Data
{
public:
Data(std::string _dp1, DataState _dp2): dp1(_dp1), dp2(_dp2) {}
Data() {}; /* Don't want this constructor because it forces a default for dp2
std::string dp1;
DataState dp2;
};
The default constructor is needed because you have factory classes which get callbacks with a "Data" object, and fill it's members on a per member basis. .i.e. something like:
Field1Callback(Data &d, const std::string &fieldVal)
{
d.dp1 = field;
}
Field2Callback(Data &d, const std:string &fieldVal)
{
d.dp2 = ConvertToState(fieldVal);
}
Are there any patterns for being explicit about what classes are allowed to call "default" constructors? i.e. serializers and parsers?
To clarify, here is some snippet code for a templated parser that I'm working with:
template<typename R>
class CSVParser
{
public:
CSVParser(std::vector<std::pair<std::string, std::function<bool(const std::string &field, R &rec)>>> parsers);
bool ProcessBuffer(const unsigned char *buffer, size_t length, size_t &bytes_parsed, bool last_buffer, std::function<void(const R& onNewRecord)> onNewRecord)
};
Example construction for parser for Data could be:
CSVParser<Data> d(
{
{
"dp1",
[](const std::string &field, Data &rec) { rec.dp1 = field; return true;}
},
{
"dp2",
[](const std::string &field, Data &rec) { rec.dp2 = ConvertToState(field); return true;}
}
}
);
Couple of solutions would be:
Make default constructor private, add an empty friend class, and then have instantiation of CSVParser which derives from friend.
Move all members for Data to a class DataRaw which exposes everything, but only use DataRaw for parsers, and use Data everywhere else in the program.
Create a DataSerialize class which derives from Data and passes garbage into constructor, knowing that it will overwrite it. Callbacks to handle constructed Data object will get passed a DataSerialize object by ref, and never know the difference.
This seems to be a common issue in other languages as well, where factory objects need to be able to break the public/private boundaries.
If you really want to be explicit about which classes can call the default constructor, you can do the following:
#include <memory>
class Factory;
void create_data(Factory &);
class Data {
Data() = default;
friend void create_data(Factory &);
};
class Factory {
std::unique_ptr<Data> _data;
public:
void set_data(std::unique_ptr<Data> &&inp) {
_data = std::move(inp);
}
std::unique_ptr<Data> make_data();
};
void create_data(Factory &f) {
f.set_data(std::unique_ptr<Data>(new Data())); // make_unique does _not_ work.
}
std::unique_ptr<Data> Factory::make_data() {
create_data(*this);
return std::move(_data);
}
int main() {
Factory f;
auto d = f.make_data();
}
But I don't think I would recommend it.

Polymorphism and casting through struct with pointers

Full disclaimer first: I have not compiled this example code, nor the real code (well, at least fully deployed). I am still wrapping my head around the problem. With that in mind, say we have this class structure:
A super base class that we will use to store instances with this base in the same container and a few "Facet" classes that we will use with multiple inheritance to encapsulate common behaviour.
class Facet_A;
class Facet_B;
class Facet_C;
struct Facet_converter
{
Facet_A * facet_a;
Facet_B * facet_b;
Facet_C * facet_c;
};
class Super_base
{
public:
virtual ~Super_base() {}
virtual Facet_converter convert()=0;
virtual const Facet_converter convert()const=0; //Notice this const...
};
class Facet_A
{
private:
int value_a;
public:
virtual ~Facet_A() {}
Facet_A():value_a(0) {}
void set_value_a(int v) {value_a=v;}
int get_value_a() const {return value_a;}
};
class Facet_B
{
private:
float value_b;
public:
Facet_B():value_b(0) {}
virtual ~Facet_B() {}
void set_value_b(float v) {value_b=v;}
float get_value_b() const {return value_b;}
};
class Facet_C
{
private:
char value_c;
public:
Facet_C():value_c('a') {}
virtual ~Facet_C() {}
void set_value_c(char v) {value_c=v;}
char get_value_c() const {return value_c;}
};
All classes that derive from these will always:
Use Super_base as a public base class, so we can store them in a vector of these.
Implement the convert methods that will return a Facet_converter object with pointers (shared, unique, raw, whatever) of the derived class casted as a particular facet (null, if not applicable).
Use Facet_A, Facet_B or Facet_C as a base class depending on what do they try to implement.
The client code would do something like...
std::vector<Super_base *> v;
//Fill super base with the good stuff.
//Let's use everything that has an integer!.
for(auto sb : v)
{
Facet_converter fc=sb->convert();
if(fc.facet_a)
{
//Do something with this integer like... std::cout<<fc.facet_a->get_value_a()<<std::endl;
}
}
//Let's use everything that has a float.
for(auto sb : v)
{
Facet_converter fc=sb->convert();
if(fc.facet_b)
{
//Do something with this float...
}
}
//Let's use everything that has a char.
for(auto sb : v)
{
Facet_converter fc=sb->convert();
if(fc.facet_c)
{
//You get the drift...
}
}
Horrible design apart (I've come to this point sick of visitors everywhere) this particular example is pretty much barebones, but you get what I am trying to do: casting down the hierarchy without using dynamic_cast and "enforcing" the compiler help (it would yell at me if I tried an assignment to a non-base class in the "convert" method).
So, a of fully implemented class...
class Derived_numeric: //This one has a float and and int
public Super_base,
public Facet_A,
public Facet_B
{
///Blah blah blah blah
virtual Facet_converter convert()
{
Facet_converter result;
result.facet_a=this;
result.facet_b=this;
result.facet_c=nullptr; //Assume no constructor for the struct that initializes the method, not really the case.
return result;
}
virtual const Facet_converter convert()const
{
const Facet_converter result;
result.facet_a=this; //Booom!!!. Error, const Derived_numeric can't be caster to Facet_A because... it's const.
result.facet_b=this;
result.facet_c=nullptr;
return result;
}
}
And there's the problem, right in the const convert method. There's a const and a non const method because the client code may work with const and non const objects but there's no way the compiler is gonna let me assign a "const this" without const casting it first.
Considering that I've come with two solutions:
const_casting the this pointer in the const method.
Creating two Facet_converter objects: Facet_converter and Facet_converter_const. They're exactly the same but one has const pointers and the other has regular pointers. Let the client code use the one they need.
Both of them suffer from horrible code repetition, since the code is almost the same and only a few details change.
I've toyed with the idea of implementing only the const one, const_casting the "this" pointer and basically lying about what the method promises. Want true constness?, add the const modifier to the result of convert() and be done with it... Seems easier, but too sneaky.
My question is, can I implement this idea without basically copying and pasting the code and being sneaky?. Remember that I need both const and non const (the derived object may change its state by using the facets, or it may not).
Now, please consider that I am not looking for "Your approach is wrong" or "I don't know why you would want to do that". This is the current situation I want to deal with and learn about. I already know I can use double dispatching or I can bastardize the whole base class to contain every other possibility... I am just looking for alternatives to it.
You could make a const Facet_converter member of Super_base and then set it via a constructor.
class Super_base
{
protected:
const Facet_converter implementations;
public:
Super_base( const Facet_converter& implementations )
: implementations( implementations ) {};
virtual ~Super_base() {};
const Facet_converter& convert() const { return implementations; }
};
When you implement the derived class, do:
Derived_numeric::Derived_numeric( ) : Super_base( Facet_converter( this, this, NULL ) )
You also need to add a constructor for the struct so that call is possible:
struct Facet_converter
{
Facet_converter( Facet_A* const& a, Facet_B* const& b, Facet_C* const& c )
{
facet_a = a;
facet_b = b;
facet_c = c;
}
Facet_A * facet_a;
Facet_B * facet_b;
Facet_C * facet_c;
};
I haven't tested this using actual pointers and subclasses, so it might need some tweaks.

How to make a member function in an inheritance hierarchy return always the same value?

I have an inheritance hierarchy and I want to make each class in this hierarchy have a set of attributes which are particular for that class and which do not change during the run of the program. For example:
class Base
{
public:
const std::string getName() const;
bool getAttribute1() const;
int getAttribute2() const;
};
Now I want these functions to return the same result all the time. Furthermore, when another class inherits Base this class should have its own set of attributes and any instance of this derived class should have the same attributes. Also the name should be unique for each class.
I want to know a way to make this as transparent and elegant as possible. Sofar I have considered 2 ideas that I can use:
Make some lock system.
That is provide setters for these attributes, but make them throw a runtime exception when they are called more than once.
Make the getters pure virtual.
In this case, the result of the functions would not be stored inside the object itself. This would make it vaguely clear that the result depends on the dynamic type.
Both ideas sound incredibly lousy, so I need your help.
I am new to C++, but I know there are a lot of idioms and patterns to solve general problems like this one. Do you know any?
I have an inheritance hierarchy and I want to make each class in this hierarchy have a set of attributes which are particular for that class and which do not change during the run of the program
Well, then just provide the corresponding values as arguments to a class constructor, and do not expose any setter method on the public interface. This will make sure the values remain constant throughout the life-time of the object.
To protect against possible errors that would alter the value of those data members from member functions of your class (which of course can access the private data), make those data members const. Notice, that this will force you to initialize those members in the constructor's initializer list.
class Base
{
public:
// Forwarding constructor (requires C++11)
Base() : Base("base", true, 42) { }
const std::string getName() const { return _s; }
bool getAttribute1() const { return _a1; }
int getAttribute2() const { return _a2; }
protected:
// Constructor that can be called by derived classes
Base(std::string s, bool a1, int a2)
: _s(s), _a1(a1), _a2(a2) { }
private:
const std::string _s;
const bool _a1;
const bool _a2;
};
Derived classes would then just construct the base subobject with the appropriate arguments:
class Derived : public Base
{
public:
// Provide the values for the constant data members to the base constructor
Derived() : Base("derived", false, 1729) { }
};
This way you would not incur in the overhead of a virtual function call, and you won't have to rewrite similar virtual functions for each of these members in derived classes.
Make them virtual and hard-code the result which the functions should return:
class Base
{
public:
virtual const std::string getName() const { return "BaseName"; }
virtual bool getAttribute1() const { return whatEverAttributeValueYouWant; }
virtual int getAttribute2() const { return attributeValueHere; }
};
class Derived : public Base {
public:
virtual const std::string getName() const { return "DerivedName"; }
virtual bool getAttribute1() const { return whatEverOtherAttributeValueYouWant; }
virtual int getAttribute2() const { return otherAttributeValueHere; }
};
If you want to describe classes rather than objects, use (kind-of) traits:
template<class T> struct AttributeValues;
template<> struct AttributeValues<Base> {
static const std::string name () { return "BaseName"; }
};
template<> struct AttributeValues<Derived> {
static const std::string name () { return "DerivedName"; }
};
//...
auto nameBase = AttributeValues<Base>::name ();
auto nameDerived = AttributeValues<Derived>::name ();

Efficient way to define an introspective C++ class hierararchy description ?

I have a C++ class hierarchy defined by inheritance and I store a description of this hierarchy in it that I can later use for introspection. I would like to know if there is a more efficient or cleaner way to define this than the way I currently do it.
Here is a stripped down version of my code
// in header file (hpp)
struct Type
{
Type( const string& n, const Type* p = nullptr ) : name(n), parent(p) {}
const string name;
const Type* parent;
};
class Base
{
public:
static const Type m_type;
virtual const Type& type() const { return m_type; }
};
class Derived : public Base
{
public:
static const Type m_type;
const Type& type() const { return m_type; }
};
// in implementation file (cpp)
const Type Base::m_type( "Base" );
const Type Derived::m_type( "Derived", &Base::m_type );
Not necessarily more efficient but think whether you actually want to require a common base class. An alternative approach uses a global type information registry. Then querying a type’s type information is done via TypeInfo::get(my_variable) or TypeInfo::get(typeid(my_type)).
This has the advantage that it also works with existing types, which just need to be added to this type info registry.
Internally, the registry would use a map from std::type_info to Type or similar. The following is a proof of concept. Unfortunately the code doesn’t compile on either clang or GCC. Based on the error messages, I’m suspecting a bug but I could also be wrong …
struct Type {
std::string name;
std::vector<Type*> parents;
// TODO Extend by fully-qualified name (namespace) etc.
template <typename... T>
Type(std::string&& name, T*... parents)
: name(name), parents{parents...} { }
};
struct TypeInfo {
template <typename T>
static Type const& get(T const&) { return get(typeid(T)); }
template <typename T>
static Type const& get() { return get(typeid(T)); }
static Type const& get(std::type_info const& info) {
auto i = types.find(info);
if (i == types.end())
throw unknown_type_error(info.name());
return i->second;
}
template <typename T>
static void register_type(Type&& type) {
types.insert(std::make_pair(typeid(T), type));
}
typedef std::unordered_map<std::type_info, Type> type_dir_t;
static type_dir_t types;
};
Full code available as gist on github.
Having a common base class for logically unrelated classes is generally frowned upon in C++, although it could be argued that this is similar to CRTP / mixins, in which common base classes are encouraged. So I’d say that there isn’t necessarily anything wrong with the approach if you don’t care for existing types.

C++ Virtual template method

I have an abstract class (I know that it will not compile this way, but it's for comprehension of what I want to do) :
class AbstractComputation {
public:
template <class T> virtual void setData(std::string id, T data);
template <class T> virtual T getData(std::string id);
};
class Computation : public AbstractComputation {
public:
template <class T> void setData(std::string id, T data);
template <class T> T getData(std::string id, T data);
};
So when I call setData<double>("foodouble", data) I want the double identified by foodouble (internal mechanism which is not the main concern here) to be set to the double data.
So how to do that?
I think that there may be a mean by typing something like virtual void setData<double>(std::string id, double data) but I don't know how to do it.
The problem is that you cannot mix static time polymorphism (templates) with runtime polymorphism easily. The reason for the language disallowing the particular construct in your example is that there are potentially infinite different types that could be instantiating your template member function, and that in turn means that the compiler would have to generate code to dynamically dispatch those many types, which is infeasible.
There are different things that can be done here to get around the limitation, basically either take away the static or the dynamic polymorphism. Removing dynamic polymorphism from the equation could be done by providing a type that is not derived from, to store the <key,value> mappings, and then offering the template that resolves that only at the base level:
class AbstractComputation {
public:
template <typename T>
void setData( std::string const & id, T value ) {
m_store.setData( id, value );
}
template <typename T>
T getData( std::string const & id ) const {
return m_store.getData<T>( id );
}
protected:
ValueStore m_store;
};
Now deriving classes can access the ValueStore from the base and there is no need for polymorphism. (This can also be done by implementing the functionality directly in AbstractComputation but it probably makes sense to separate concerns)
The other option is to maintain runtime polymorphism, but remove static polymorphism. This can be done by performing type erasure on the base class and then dispatching to the appropriate (non-templated) function that takes the type-erased arguments. The simplest version of this is just using boost::any:
class AbstractComputation {
public:
template <typename T>
void setData( std::string const & id, T value ) {
setDataImpl( id, boost::any( value ) );
}
template <typename T>
T getData( std::string const & id ) const {
boost::any res = getDataImpl( id );
return boost::any_cast<T>( res );
}
protected:
virtual void setDataImpl( std::string const & id, boost::any const & value ) = 0;
virtual boost::any getDataImpl( std::string const & id ) const = 0;
};
How type erasure is implemented under the hood is interesting, but out of the scope here, the important part is that a boost::any is a concrete (non-templated) type that can store any type internally by using type erasure on the arguments, and at the same time allows for type-safe retrieval of the data.
In some cases it may be enough to move the templating from method level to class level, e.g.:
#include <iostream>
template<typename T>
class AbstractComputation {
public:
virtual void setData(std::string id, T data)
{
std::cout << "base" << std::endl;
}
};
template<typename T>
class Computation : public AbstractComputation<T> {
public:
virtual void setData(std::string id, T data)
{
std::cout << "derived" << std::endl;
}
};
int main()
{
AbstractComputation<int> *x = new Computation<int>();
x->setData("1", -1);
delete x;
return 0;
}
You can probably use boost::any in your case.
virtual void setData(std::string id, boost::any data);
It is a wrapper that can encapsulate almost anything.
More info on a similar topic in this answer.
First, you cannot have virtual template functions. As templates are resolved at compile time, virtual will not work, as the compiler would not know which template to pick. See here, for more info about this.
If you know list of possible types in advance, preprocessor may help:
#define MY_CLASSES MYTYPE(int) MYTYPE(float) MYTYPE(double)
class AbstractComputation {
public:
# define MYTYPE(T) virtual void setData(std::string id, T data)=0;\
virtual void getData(std::string id, T& dst_data)=0;
MY_CLASSES
# undef MYTYPE
};
class Computation : public AbstractComputation {
public:
# define MYTYPE(T) virtual void setData(std::string id, T data){std::cout<<"writing: "<<data<<std::endl;}\
virtual void getData(std::string id, T& dst_data){dst_data=0;/*put your actual implementation here*/}
MY_CLASSES
# undef MYTYPE
};
If you don't know a complete list of possible types, perhaps, your problem is unresolvable. Type erasure, as mentioned by others, may also help.. but not in all circumstances.
Use boost::any to accept the datum, and then when you actually set, grab the correct type from it.