Enforce constness for pointed data in C++? - c++

Let there be a Foo class with some const and non-const methods
struct Foo
{
Foo ();
~Foo();
void noSideEffect() const;
void withSideEffect();
};
I also have a Bar class, that need to refer to Foo in some way. To be more precise, maybe too precise for this question, Bar implements operators || and && for union and intersections, so two Bar instances need to kwow they are working on the same instance of Foo.
The simplest solution I found was to use a pointer to a Foo object:
struct Bar
{
Foo * p_foo;
Bar (Foo& foo)
: p_foo(&foo) {};
}
Now two bar instances can play together and see if they are both handling the same Foo. I'm almost happy.
But now I would like to sometimes use Bar with const Foo instances. Well, it might be easy, I just have to create a const Bar instance, right? There we go:
const Bar createBarFromConstFoo(const Foo& foo)
{
Foo* newfoo = const_cast<Foo*>(&foo);
const Bar newbar (*newfoo);
return newbar;
}
And now the nightmare begins (see Why doesn't C++ enforce const on pointer data?). I think I understand the why (the standard says so), my main problem is how to best cope with it.
Except this little standard thing, the createBarFomConstFoo does almost what I want since it is returning a const Bar.
Is there a way to prevent a const Bar to do nasty things with my (initially) const Foo (ie only call const methods of Foo) while allowing a non-const Bar to do everything?
Maybe there is no way to do that and it's an object design issue, but I do not see a simple alternative.
Edit: to downvoters, can you please explain why, I may be able to progress from your remarks...
Edit 2: Maybe obfuscating the real classes behing Foo and Bar was a bad idea, I just wanted to simplify things.
So Foo is in fact a Molecule (and in fact a Protein), which contains Atoms (many for a protein). Being able to select some atoms is the reason to create Bar, which is a SelectionOfAtoms.
It is sometimes convenient to select, from example, all hydrogens and oxygen atoms, so Bar implements unions and intersections. I want to be able to extract those atoms so SelectionOfAtoms implements a createNewMolecule() methods from the selected atoms. It therefore need a way to refer to the original molecule (maybe some kind of copy would do here but maybe not with the other requirements below).
But I recently felt the need to modify atoms of a selection, while keeping other atoms unmodified. Doing it through SelectionOfAtoms (Bar) was conveninent: it already knows where to find the Atoms (using the pointer) and the index of these atoms (internal implementation detail), so everything needed to change atoms is almost already here, except that I can either use Selection only on Molecule (non-const) or work on const Molecule and forget about modifying them or go into the const_cast horror.
I'm sure it's a pretty bad design, but it is what is already there, it can surely be improved a lot.

Using the STL as a guide, consider your molecule as a container, and your selection as something like an iterator or iterator range.
Now, in this scheme you'd have separate types for the const and non-const selections/iterators, which makes sense since they have different semantics. Making the constness a template parameter is probably a false economy unless there's a lot more code in the selection than you've suggested.
Now, you start off with either a const or a non-const molecule, and you know statically that you're getting ether a const_selection or (non-const) selection.

It Bar is not overly complex, you can make it a class template.
template <typename FooType>
struct Bar
{
FooType * p_foo;
Bar (FooType& foo)
: p_foo(&foo) {};
}
template <typename FooType>
Bar<FooType> makeBar(FooType& foo)
{
return Bar<FooType>(foo);
}

Related

C++ API: Modifing internal objects

I've got two related questions.
At the moment I am designing/writing a C++ API, in which I need to be able to modify an object that is held by another object.
It is comparable to this example:
class Bar
{
public:
Bar(int x) : num(x){}
void setNum(int x)
{
num = x;
}
int getNum()
{
return num;
}
private:
int num;
};
class Foo
{
public:
Foo() = default;
void setBar(std::unique_ptr<Bar> newBar)
{
bar = std::move(newBar);
}
Bar* getBar()
{
return bar.get();
}
private:
std::unique_ptr<Bar> bar;
};
The class Foo takes ownership of Bar, however, Bar must be able to be modified.
Here, Foo is the main class the user would interact with.
Whilst Bar could be considered more as a data type, which changes the output of Foo.
Is the solution of returning a raw pointer to Bar the preferred option?
I have the feeling, that this brakes the encapsulation which is a no-go for API design.
My googling efforts haven't given me a concrete answer to exactly this problem yet.
But I might just be looking with the wrong search terms.
The second part to this question is, how this example would change, if Bar would be stored in a container in Foo.
Would I return a pointer to the whole container, an iterator for the container ...?
If you worry about getBar breaking the encapsulation, then you should also see void setBar(std::unique_ptr<Bar> newBar) as such a breakage.
Because allowing to set bar from outside does make the knowledge about bar possibly none exclusive to Foo and the one passing Bar to Foo might have still the possibility to modify the bar so Foo can no do any assumptions about the state of Bar, as it could change anytime.
On the other hand, if you only want to have reading access to Bar trough Foo then a const Bar* getBar() or const Bar& getBar() would not break the encapsulation that much, because getBar would not allow changing Bar.
Is the solution of returning a raw pointer to Bar the preferred option?
It's a solution and not necessarily a bad one. Returning a reference would be preferable in cases where the object always exists (not in this case since Foo's default constructor doesn't create a Bar).
Some programmers prefer to use a wrapper for bare pointers (such as observer_ptr, which has been proposed to the standard) to distinguish it from a pointer whose purpose is to iterate an array, or from owning bare pointers (latter of which should be avoided).
I have the feeling, that this brakes the encapsulation
Your whole premise is to break the encapsulation since you want to "modify internal objects". If you want to avoid breakage of encapsulation, then you may need to change the design further up so that you don't need to modify internal objects (externally).
A solution that doesn't break encapsulation is to provide a specific interface to Foo for modification, such as:
void Foo::transmogrify_bar(int gadgets) {
bar->transmofgrify(gadgets);
}
Whether this encapsulation is useful for your API is another matter. In some cases it is essential, in others it doesn't matter much.
if Bar would be stored in a container in Foo. Would I return a pointer to the whole container, an iterator for the container ...?
Would you want the client to be able to modify the container (add, remove elements)?
This is breaking the encapsulation further. Instead, you could have begin and end iterators that don't allow modification of the container itself, which brings you to an equivalent encapsulation of the pointer return in the case of single object.
You could provide only const iterators, and add iterator as an argument to transmogrify to keep encapsulation of modifying Bar.
Finally, for full encapsulation, you would need to use PIMPL pattern to hide Bar completely.

Can I be sure than a const reference is updated when modified by another entity?

I have a class Foo having the rights to read an instance of class Bar, but doesn't have the rights to modify it. In the same time, the instance of Bar could be modified by other elements.
For the moment, I implement it by this way:
class Foo
{
private:
const Bar& bar; // Foo can't modify it
public:
Foo(const Bar& bar_) : bar(bar_) {}
void doSomthing() { this->bar.printData(); }
};
And it could be used like this:
Bar bar;
Foo foo(bar);
bar.update(); // This modify the instance of Bar
foo.doSomthing(); // This use the reference to (modified) bar
My question is: With this implementation, can I be sure than the compiler doesn't use a non updated copy of bar even if the reference is declared as const ?
If no, how can I do that ?
Note: I don't use C++11 for compatibility reason
Yes, you can be sure. References are internally implemented in the compiler as pointers, and both bar.update(); and Foo::bar are acting on the same memory location.
That's, of course, as long as there are no data race concerns, at which point the usual problems of synchronization arise.
The best pre c++11 standard text I could find quickly was this draft from 2005, wich should be close enough to C++03.
It says in 3.10:13 [basic.lval]
The referent of a const-qualified expression shall not be modified (through that expression), except that if it is of class type and has a mutable component, that component can be modified.
The emphasis is mine and highlights that it is to be expected that the referent can be modified though other expressions (if they themselves allow it).

How to imitate a class behaviour with implicit-cast operator

Suppose, there are 2 classes, Foo and ImitateFoo.
ImitateFoo implements an implicit cast operator to act like Foo.
class Foo
{
public:
int DoFoo() { return 1; }
};
class ImitateFoo
{
private:
Foo f;
public:
operator Foo&() { return f; }
};
I want to act on ImitateFoo, like I do on Foo. Especially calling its methods.
ImitateFoo imitator;
Foo& f = imitator; // implicit cast works
f.DoFoo();
static_cast<Foo&>(imitator).DoFoo(); // static cast works as well
imitator.DoFoo(); // does NOT compile -- desired behaviour!
Unfortunately, the last approach does not compile (at least with VS 10.0).
It's for some reasons not possible to overload the .-operator.
Any suggestions how I can achieve the desired behaviour? Is it somehow possible to increase the binding-priority of the cast-operator against the .-operator?
Edit: Why I cannot use Inheritance as the most obvious solution
I have to re-implement a bunch of framework classes. Foo resembles one of them and it's used as a global object throughout the legacy code (which I must not change).
Since I am now in need for unit tests, I need to control the state of these global objects. This is done quite similarly to the way the
PIMPL idiom proposes.
In that case the ImitateFoo class has only one state: it's implementation which is injected and might be changed during runtime. All method calls are redirected to this Foo instance. So actually I could implement the example above as easy as just make a DoFoo non-virtual function in ImitateFoo with redirects to its currents implementation method. Which is in fact what I am doing now.
This works pretty well both for methods and also for operators. But it results in A LOT of bloat code, which does nothing than redirecting.
Contrary to redirecting each method and operator-call by it's own, I wanted to take a step back and look if it's possible to just make the ImitateFoo behave like it's underlaying implementation.
In dynamic languages like Python you could delegate all non explicitely defined methods to another object (here field f). But AFAIK it is not possible in C++.
If inheritance is not an acceptable solution you can explicitely delegate all methods you want ImitateFoo do process, in a kind of duck typing instead of inheritance :
class ImitateFoo
{
private:
Foo f;
public:
operator Foo&() { return f; }
int DoFoo() { return f.DoFoo(); } // explicit delegation
};
It is not as automatic as you could want, but at least :
imitator.DoFoo();
will correctly compile and run.
Seems a bit like a X Y problem, and your proposed solution, although elegant in concept, I don't believe it's possible in C++.
Running in a problem somewhat similar to yours I've used macros to hide the repetitive code, which in your case would be the casting(considering that the actual problem you want is to avoid is to re-write every function/operator , main goal being reducing the amount of code to be written) .
Here's a code snippet
#define CAST(x) (static_cast<Foo&>(x))
...
ImitateFoo f;
CAST(f).DoFoo();

encapsulation difficulty in nested c++ classes

We all are familiar with the concept of encapsulation and abstraction but sometimes this may lead to an obstacle I'm curious about the tricks or methods or whatever you call them to solve the problem.
here we have a nested c++ class:
#include <iostream>
using namespace std;
class Foo {
public:
int get_foo_var()
{
return foo_var;
}
void set_foo_var(int a)
{
foo_var = a;
}
private:
int foo_var;
};
class Bar {
public:
Foo get_foo()
{
return foo;
}
private:
Foo foo;
};
int main()
{
Bar bar;
bar.get_foo().set_foo_var(2);
cout << bar.get_foo().get_foo_var() << endl;
}
as you see here, get_foo() returns a copy of foo_var(it's value) which means it is not the reference to the original one and changing it does nothing, thus nothing is changed.
one solution might be changing to get_foo() in a way that returns a reference and not a value but this is of course in contrast with the concept of encapsulation.
what are the solutions to solve this problem without breaking software designing principles?
UPDATE
one pointed out setting foo_var by a function in bar class:
class Bar {
public:
void set_foo_var(int a) {
foo.set_foo_var(a);
}
private:
Foo foo;
};
but I think this violates encapsulation and abstraction! the whole concept of abstraction is if "foo" is related to "Foo" and "bar" is related to "Bar", that most of foo manipulations should be done in Foo class and some manipulations can be applied in other classes. what about the first situtation? (the situtation in which foo manipulation has nothing to do with Bar and so manipulating foo in bar is stupid!)
Whether you want to return a copy of or a reference to something is a high-level design decision. Both ways can be required, depending on the context.
In this particular example, you could add a corresponding method in Bar to modify the Foo behind it:
class Bar {
public:
void set_foo_var(int a) {
foo.set_foo_var(a);
}
private:
Foo foo;
};
Is this good or bad? The answer is: we cannot tell you. Generally, it's hard to seriously talk about good class design with names like "Foo" and "Bar". What's good and bad depends on the actual, real usage scenario! :)
Let's look at this from a purely conceptual level for a minute. This what your design says:
There exists one conceptual Foo entity for every Bar instance (because I can get a Foo from a Bar, and its state depends on which Bar I get it from).
Each Foo instance belongs to the Bar instance it came from (because operations on a Foo change the Bar it came from - the next time I ask for a Foo from a Bar, the previous Foo's changes are reflected).
A Foo has the same lifetime as its Bar (because I can ask for it at any time in the Bar's lifetime, I can use it as long as Bar exists, and the caller of get_foo() does not manage the lifetime of the returned Foo object).
Another way of looking at it is that Foo is already designed as part of Bar's internal state, a "conceptual member variable", regardless of whether it is actually implemented that way.
Given what your public interface is already telling you, how does returning a non-const reference to a private member really break encapsulation? Could you change the implementation so that Foo isn't a private member variable, yet still use the same public interface? Yes, you could. The only implementation changes that would force you to change the public interface ALSO force you to change the conceptual interface described above.
Implementation rules of thumb can be over-applied. Move past mechanics and look at conceptual design instead. Assuming you're OK with what your design is implying, in this case I say that returning a reference to a private member variable does NOT break encapsulation. At least that's my take on it.
An alternative is to have Foo and Bar less tightly coupled.
class Bar {
public:
Foo get_foo()
{
return foo;
}
set_foo(Foo new_foo)
{
// Update foo with new_foo's values
foo = new_foo;
}
private:
Foo foo;
};
In this case, Foo reflects some part of Bar's internal state at the time it was requested, but isn't tied to the Bar it came from. You have to explicitly call set_foo() to update Bar. Without that requirement, Foo really is conceptually a member variable regardless of how you implement it.

c++ template casting

I'm a little lost in how to cast templates. I have a function foo which takes a parameter of type ParamVector<double>*. I would like to pass in a ParamVector<float>*, and I can't figure out how to overload the casting operator for my ParamVector class, and Google isn't helping me that much. Does anyone have an example of how to do this? Thanks.
EDIT: Adding some code, sorry I'm an idiot and didn't phrase the original question well at all;
template<class T> class ParamVector
{
public:
vector <T> gnome;
vector <T> data_params;
}
template<class T> class ParamVectorConsumer
{
public:
ParamVector<T> test;
}
ParamVector<float> tester;
ParamVectorConsumer<double> cons;
cons.ParamVector = tester
will fail to compile. I would like to know how to write it so that I can cast the float version of tester to a ParamVector double. Thanks
EDIT2: Casting was the wrong word. I don't mind writing extra code, I just need to know how to get this to be accepted by the compiler so that I can write some sort of conversion code.
I'm not sure but maybe you need some like this:
template< typename TypeT >
struct ParamVector
{
template < typename NewTypeT >
operator ParamVector< NewTypeT >()
{
ParamVector< NewTypeT > result;
// do some converion things
return result;
}
template< typename NewTypeT >
ParamVector( const ParamVector< NewTypeT > &rhs )
{
// convert
}
template < typename NewTypeT >
ParamVector& operator=( const ParamVector< NewTypeT > &rhs )
{
// do some conversion thigns
return *this;
}
};
ParamVector< double > d1;
ParamVector< float > f1;
f1 = d1;
You can choose use conversion operator or operator= - I've provided both in my example.
Well, you can't. Each different actual template parameter, makes an entirely new class, which has no* relation inheritance relation with any any other class, with a diffent actual argument, made from that template.
No relationship. Well, except that each provides the same interface, so that inside a template you can handle then the same.
But neither the static types or the dynamic types have any relation.
Let me drop back here, and explain.
When I declare a pointer to classtype, like
Foo fp*;
fp has what we call a static type, of pointer-to Foo. If class Bar is a subclass of Foo, and I point fp at new Bar:
fp = new Bar1();
then we say that the object pointed to by fp has the dynamic type of Bar.
if Bar2 also publicly derives from Foo, I can do this:
fp = new Bar2();
and without ever even knowing what fp points to, I can call virtual methods declared in Foo, and have the compiler make sure that the method defined in he dynamic type pointed to is what's called.
For a template< typename T > struct Baz { void doSomething(); };
Baz<int> and Baz<float> are two entirely different class types, with no relationship.
The only "relationship" is that I can call doSomething() on both, but since the static types have no relationship, if I have a Baz<int> bi*, I can't point it to a Baz<float>. Not even with a cast. The compiler has no way to "translate" a call to the Baz doSotheing method into a call to a Baz::doSomething() method. That's because there is no "Baz method", there is no Baz, there are ony Baz<int>s and Baz<float>s, and Baz<whatevers>, but there's no common parent. Baz is not a class, Baz is a template, a set of instructions about how to make a class if and only if we have a T parameter that's bound to an actual type (or to a constant).
Now there is one way I can treat those Bazes alike: in a template, they present the same interface, and the compiler, if it knows what kind of Baz we're really dealing with, can make a static call to that method (or a static access of a member variable).
But a template is not code, a template is meta-code, the instructions of how to synthesize a class. A "call" in a template is not a call,it's an instruction of how to write the code to make a call.
So. That was long winded and confusing. Outside of a template definition, there is no relationship between a ParamVector and aParamVector. So your assignment can't work.
Well. Almost.
Actually, with partial application of templates, you can write a template function which gives a "recipe" of how to transform a Paramvector<T> to a ParamVector<U>. Notice the T and the U. If you can write code to turn any kind of ParamVector, regardless of actual template parameter into any other kind of ParamVector, you can package that up as a partially applied template, and the compiler will add that function to, for example, ParamVector.
That probably involves making a ParamVector<U>, and transforming each T in the ParamVector<T> into a U to put in the ParamVector<U>. Which still won't let you asign to a ParamConsumer<T>.
So maybe you want to have both templates and inheritance. In that case, you can same that all ParamVectors regardless of type inherit from some non-template class. And then there would be a relationship between ParamVectors, they'd all be sibling subclasses of that base class.
Notice that when you do an implicit cast, what the compiler can do without your help (I mean, without additional code) is just reference-upcast. That means that, seeing the object as a reference (for cast purposes only, the nature of the object doesn't change of course), it can look at it as one of its ancestors. When you have two template instances, none of them is an ancestor of the other (neither they are necessarily in the same hierarchy).
After trying that, the compiler looks for cast operators, constructors, etc. At this stage, probably a temporary object needs to be created, except when you're doing attribution and there's an attribution operator that fits.
One solution to your problem would be to use a conversion constructor:
template<class T> class ParamVector
{
public:
vector <T> gnome;
vector <T> data_params;
ParamVector()
{
}
template <class T2> ParamVector(const ParamVector<T2> &source)
{
gnome.reserve(source.gnome.size());
copy(source.gnome.begin(), source.gnome.end(), gnome.begin());
data_params.reserve(source.data_params.size());
copy(source.data_params.begin(), source.data_params.end(), data_params.begin());
}
};
This would create a temporary object whenever you use an instance of the template and other is required. Not a good solution if you're dealing with large containers, the overhead isn't acceptable. Also, if you pass a template instance to a function that requires not an object but a reference, the compiler won't call the conversion constructor automatically (you have to do an explicit call).
You are lost because you can't do it - the two types are completely different. Whenever you come across the need for a cast in your code, you should examine both your code and your design very closely - one or both is probably wrong.
You can't do this with a direct cast because double and float are completly different sizes. Doubles are going to be 64 bits while floats are 32. A pointer forced to cast from a
ParamVector<float>
to
ParamVector<double>
is going to misinterpret the data and give you garbage. You may want to google "pointer aliasing" or just learn more about pointers in general to see how this isn't going to work.
Think about it for a second you have one array that is a bunch of 64 bit values with fields layed out like this
0 => abcdabcd12341234
1 => abcdabcd12341234
If you force this to be interpreted as an array of 32 bit values, its going to not be interpreted correctly. You may or may not get something like
0 => abcdabcd
1 => 12341234
2 => abcdabcd
3 => abcdabcd
or it could be switched so that the 12341234's come first, or something stranger due to how the word ordering works out.
You mentioned "template casting" in your headline, so I'll presume that ParamVector is a templated type. That means that foo could be templated as well, and that would solve your problem.
template <typename T>
void foo(ParamVector<T> const& data)
{
}
You can't cast templates like this because the types are unrelated.
However, you can add a conversion function, such as:
(Your code wasn't really complete, so I can post complete code either. Hopefully you will get the idea.)
template<class T> class ParamVectorConsumer
{
public:
ParamVector<T> test;
template<T2> ParamVectorConsumer<T2> convert()
{
ParamVectorConsumer<T2> ret;
ret = this->...
}