I would like to know if its possible to call a non-const member function from a const member function. In the example below First gives a compiler error. I understand why it gives an error, I would like to know if there is a way to work around it.
class Foo
{
const int& First() const
{
return Second();
}
int& Second()
{
return m_bar;
}
int m_bar;
}
I don't really want to discuss the wisdom of doing this, I'm curious if its even possible.
return (const_cast<Foo*>(this))->Second();
Then cry, quietly.
It is possible:
const int& First() const
{
return const_cast<Foo*>(this)->Second();
}
int& Second() { return m_bar; }
I wouldn't recommend this; it's ugly and dangerous (any use of const_cast is dangerous).
It's better to move as much common functionality as you can into helper functions, then have your const and non-const member functions each do as little work as they need to.
In the case of a simple accessor like this, it's just as easy to return m_bar; from both of the functions as it is to call one function from the other.
By the definition of const, a function should not modify the state of an object. But if it calls another non-const member, the object's state might get changed, so it's disallowed.
I know you said you didn't want to hear about this, but I think it's important for others that happen upon the question.
The restriction of const member methods are came from compile time. If you can fool the compiler, then yes.
class CFoo
{
public:
CFoo() {m_Foo = this;}
void tee();
void bar() const
{
m_Foo->m_val++; // fine
m_Foo->tee(); // fine
}
private:
CFoo * m_Foo;
int m_Val;
};
This actually abolishes the purpose of const member function, so it is better not to do it when design a new class. It is no harm to know that there is a way to do it,especially it can be used as an work-around on these old class that was not well designed on the concept of const member function.
Overload on const:
const int& Second() const
{
return m_bar;
}
You can add this method and keep the original non-const version.
iterators are similar in this and make an interesting study.
const iterators are often the base for 'non const' iterators, and you will often find const_cast<>() or C style casts used to discard const from the base class with accessors in the child.
Edit:
Comment was
I have a zip iterator where the const one inherits from the non-const
This would generally be the wrong inheritence structure (if your saying what I think you are), the reason being that children should not be less restrictive than parents.
say you had some algorithm taking your zip iterator, would it be appropriate to pass a const iterator to a non const ?
if you had a const container, could only ask it for a const iterator, but then the const iterator is derived from an iterator so you just use the features on the parent to have non const access.
Here is a quick outline of suggested inheritence following the traditional stl model
class ConstIterator:
public std::_Bidit< myType, int, const myType *, const mType & >
{
reference operator*() const { return m_p; }
}
class Iterator : public ConstIterator
{
typedef ConstIterator _Mybase;
// overide the types provided by ConstIterator
typedef myType * pointer;
typedef myType & reference;
reference operator*() const
{
return ((reference)**(_Mybase *)this);
}
}
typedef std::reverse_iterator<ConstIterator> ConstReverseIterator;
typedef std::reverse_iterator<Iterator> ReverseIterator;
I found myself trying to call a non-const member function that was inherited, but was actually const because of the API I was using. Finally I settled on a different solution: re-negotiate the API so that the function I inherit is properly const.
It won't always be possible to negotiate changes to others' functions, but doing so when possible seems cleaner and nicer than needing to use const_cast and it benefits other users as well.
Related
I'm working on learning C++ with Stroustrup's (Programming Principles & Practice Using C++) book. In an exercise we define a simple struct:
template<typename T>
struct S {
explicit S(T v):val{v} { };
T& get();
const T& get() const;
void set(T v);
void read_val(T& v);
T& operator=(const T& t); // deep copy assignment
private:
T val;
};
We're then asked to define a const and a non-const member function to get val.
I was wondering: Is there any case where it makes sense to have non-const get function that returns val?
It seems much cleaner to me that we can't change the value in such situations indirectly. What might be use cases where you need a const and a non-const get function to return a member variable?
Non-const getters?
Getters and setters are merely convention. Instead of providing a getter and a setter, a sometimes used idiom is to provide something along the line of
struct foo {
int val() const { return val_; }
int& val() { return val_; }
private:
int val_;
};
Such that, depending on the constness of the instance you get a reference or a copy:
void bar(const foo& a, foo& b) {
auto x = a.val(); // calls the const method returning an int
b.val() = x; // calls the non-const method returning an int&
};
Whether this is good style in general is a matter of opinion. There are cases where it causes confusion and other cases where this behaviour is just what you would expect (see below).
In any case, it is more important to design the interface of a class according to what the class is supposed to do and how you want to use it rather than blindly following conventions about setters and getters (eg you should give the method a meaningful name that expresses what it does, not just in terms of "pretend to be encapsulated and now provide me access to all your internals via getters", which is what using getters everywhere actually means).
Concrete example
Consider that element access in containers is usually implemented like this. As a toy example:
struct my_array {
int operator[](unsigned i) const { return data[i]; }
int& operator[](unsigned i) { return data[i]; }
private:
int data[10];
};
It is not the containers job to hide the elements from the user (even data could be public). You dont want different methods to access elements depending on whether you want to read or write the element, hence providing a const and a non-const overload makes perfectly sense in this case.
non-const reference from get vs encapsulation
Maybe not that obvious, but it is a bit controversial whether providing getters and setters supports encapsulation or the opposite. While in general this matter is to a large extend opinion based, for getters that return non const references it is not so much about opinions. They do break encapuslation. Consider
struct broken {
void set(int x) {
counter++;
val = x;
}
int& get() { return x; }
int get() const { return x; }
private:
int counter = 0;
int value = 0;
};
This class is broken as the name suggests. Clients can simply grab a reference and the class has no chance to count the number of times the value is modified (as the set suggests). Once you return a non-const reference then regarding encapsulation there is little difference to making the member public. Hence, this is used only for cases where such behaviour is natural (eg container).
PS
Note that your example returns a const T& rather than a value. This is reasonable for template code, where you dont know how expensive a copy is, while for an int you wont gain much by returning a const int& instead of an int. For the sake of clarity I used non-template examples, though for templated code you would probably rather return a const T&.
First let me rephrase your question:
Why have a non-const getter for a member, rather than just making the member public?
Several possible reasons reasons:
1. Easy to instrument
Whoever said the non-const getter needs to be just:
T& get() { return val; }
? it could well be something like:
T& get() {
if (check_for_something_bad()) {
throw std::runtime_error{
"Attempt to mutate val when bad things have happened");
}
return val;
}
However, as #BenVoigt suggests, it is more appropriate to wait until the caller actually tries to mutate the value through the reference before spewing an error.
2. Cultural convention / "the boss said so"
Some organizations enforce coding standards. These coding standards are sometimes authored by people who are possibly overly-defensive. So, you might see something like:
Unless your class is a "plain old data" type, no data members may be public. You may use getter methods for such non-public members as necessary.
and then, even if it makes sense for a specific class to just allow non-const access, it won't happen.
3. Maybe val just isn't there?
You've given an example in which val actually exists in an instance of the class. But actually - it doesn't have to! The get() method could return some sort of a proxy object, which, upon assignment, mutation etc. performs some computation (e.g. storing or retrieving data in a database; or flipping a bit, which itself is not addressable like an object needs to be).
4. Allows changing class internals later without changing user code
Now, reading items 1. or 3, above, you might ask "but my struct S does have val!" or "by my get() doesn't do anything interesting!" - well, true, they don't; but you might want to change this behavior in the future. Without a get(), all of your class' users will need to change their code. With a get(), you only need to make changes to the implementation of struct S.
Now, I don't advocate for this kind of a design approach approach, but some programmers do.
get() is callable by non const objects which are allowed to mutate, you can do:
S r(0);
r.get() = 1;
but if you make r const as const S r(0), the line r.get() = 1 no longer compile, not even to retrieve the value, that's why you need a const version const T& get() const to at least to able to retrieve the value for const objects, doing so allows you do:
const S r(0)
int val = r.get()
The const version of member functions try to be consistent with the constness property of the object the call is made on, i.e if the object is immutable by being const and the member function returns a reference, it may reflect the constness of the caller by returning a const reference, thus preserving the immutability property of the object.
It depends on the purpose of S. If it's some kind of a thin wrapper, it might be appropriate to allow the user to access the underlaying value directly.
One of the real-life examples is std::reference_wrapper.
No. If a getter simply returns a non-const reference to a member, like this:
private:
Object m_member;
public:
Object &getMember() {
return m_member;
}
Then m_member should be public instead, and the accessor is not needed. There is absolutely no point making this member private, and then create an accessor, which gives all access to it.
If you call getMember(), you can store the resulting reference to a pointer/reference, and afterwards, you can do whatever you want with m_member, the enclosing class will know nothing about it. It's the same, as if m_member had been public.
Note, that if getMember() does some additional task (for example, it doesn't just simply return m_member, but lazily constructs it), then getMember() could be useful:
Object &getMember() {
if (!m_member) m_member = new Object;
return *m_member;
}
I'm working on learning C++ with Stroustrup's (Programming Principles & Practice Using C++) book. In an exercise we define a simple struct:
template<typename T>
struct S {
explicit S(T v):val{v} { };
T& get();
const T& get() const;
void set(T v);
void read_val(T& v);
T& operator=(const T& t); // deep copy assignment
private:
T val;
};
We're then asked to define a const and a non-const member function to get val.
I was wondering: Is there any case where it makes sense to have non-const get function that returns val?
It seems much cleaner to me that we can't change the value in such situations indirectly. What might be use cases where you need a const and a non-const get function to return a member variable?
Non-const getters?
Getters and setters are merely convention. Instead of providing a getter and a setter, a sometimes used idiom is to provide something along the line of
struct foo {
int val() const { return val_; }
int& val() { return val_; }
private:
int val_;
};
Such that, depending on the constness of the instance you get a reference or a copy:
void bar(const foo& a, foo& b) {
auto x = a.val(); // calls the const method returning an int
b.val() = x; // calls the non-const method returning an int&
};
Whether this is good style in general is a matter of opinion. There are cases where it causes confusion and other cases where this behaviour is just what you would expect (see below).
In any case, it is more important to design the interface of a class according to what the class is supposed to do and how you want to use it rather than blindly following conventions about setters and getters (eg you should give the method a meaningful name that expresses what it does, not just in terms of "pretend to be encapsulated and now provide me access to all your internals via getters", which is what using getters everywhere actually means).
Concrete example
Consider that element access in containers is usually implemented like this. As a toy example:
struct my_array {
int operator[](unsigned i) const { return data[i]; }
int& operator[](unsigned i) { return data[i]; }
private:
int data[10];
};
It is not the containers job to hide the elements from the user (even data could be public). You dont want different methods to access elements depending on whether you want to read or write the element, hence providing a const and a non-const overload makes perfectly sense in this case.
non-const reference from get vs encapsulation
Maybe not that obvious, but it is a bit controversial whether providing getters and setters supports encapsulation or the opposite. While in general this matter is to a large extend opinion based, for getters that return non const references it is not so much about opinions. They do break encapuslation. Consider
struct broken {
void set(int x) {
counter++;
val = x;
}
int& get() { return x; }
int get() const { return x; }
private:
int counter = 0;
int value = 0;
};
This class is broken as the name suggests. Clients can simply grab a reference and the class has no chance to count the number of times the value is modified (as the set suggests). Once you return a non-const reference then regarding encapsulation there is little difference to making the member public. Hence, this is used only for cases where such behaviour is natural (eg container).
PS
Note that your example returns a const T& rather than a value. This is reasonable for template code, where you dont know how expensive a copy is, while for an int you wont gain much by returning a const int& instead of an int. For the sake of clarity I used non-template examples, though for templated code you would probably rather return a const T&.
First let me rephrase your question:
Why have a non-const getter for a member, rather than just making the member public?
Several possible reasons reasons:
1. Easy to instrument
Whoever said the non-const getter needs to be just:
T& get() { return val; }
? it could well be something like:
T& get() {
if (check_for_something_bad()) {
throw std::runtime_error{
"Attempt to mutate val when bad things have happened");
}
return val;
}
However, as #BenVoigt suggests, it is more appropriate to wait until the caller actually tries to mutate the value through the reference before spewing an error.
2. Cultural convention / "the boss said so"
Some organizations enforce coding standards. These coding standards are sometimes authored by people who are possibly overly-defensive. So, you might see something like:
Unless your class is a "plain old data" type, no data members may be public. You may use getter methods for such non-public members as necessary.
and then, even if it makes sense for a specific class to just allow non-const access, it won't happen.
3. Maybe val just isn't there?
You've given an example in which val actually exists in an instance of the class. But actually - it doesn't have to! The get() method could return some sort of a proxy object, which, upon assignment, mutation etc. performs some computation (e.g. storing or retrieving data in a database; or flipping a bit, which itself is not addressable like an object needs to be).
4. Allows changing class internals later without changing user code
Now, reading items 1. or 3, above, you might ask "but my struct S does have val!" or "by my get() doesn't do anything interesting!" - well, true, they don't; but you might want to change this behavior in the future. Without a get(), all of your class' users will need to change their code. With a get(), you only need to make changes to the implementation of struct S.
Now, I don't advocate for this kind of a design approach approach, but some programmers do.
get() is callable by non const objects which are allowed to mutate, you can do:
S r(0);
r.get() = 1;
but if you make r const as const S r(0), the line r.get() = 1 no longer compile, not even to retrieve the value, that's why you need a const version const T& get() const to at least to able to retrieve the value for const objects, doing so allows you do:
const S r(0)
int val = r.get()
The const version of member functions try to be consistent with the constness property of the object the call is made on, i.e if the object is immutable by being const and the member function returns a reference, it may reflect the constness of the caller by returning a const reference, thus preserving the immutability property of the object.
It depends on the purpose of S. If it's some kind of a thin wrapper, it might be appropriate to allow the user to access the underlaying value directly.
One of the real-life examples is std::reference_wrapper.
No. If a getter simply returns a non-const reference to a member, like this:
private:
Object m_member;
public:
Object &getMember() {
return m_member;
}
Then m_member should be public instead, and the accessor is not needed. There is absolutely no point making this member private, and then create an accessor, which gives all access to it.
If you call getMember(), you can store the resulting reference to a pointer/reference, and afterwards, you can do whatever you want with m_member, the enclosing class will know nothing about it. It's the same, as if m_member had been public.
Note, that if getMember() does some additional task (for example, it doesn't just simply return m_member, but lazily constructs it), then getMember() could be useful:
Object &getMember() {
if (!m_member) m_member = new Object;
return *m_member;
}
is it ok to use const_cast in that case or are there any caveats:
class A{
public:
A() : m_someData(5)
{}
int& get() { return m_someData;};
const int& get() const { const_cast<A*>(this)->get(); };
private:
int m_someData;
};
the intention is that the get routine may be much more complicated and code duplication should be avoided.
No. I wouldn't suggest that. I would suggest you to use const_cast in reverse direction:
int& get() { return const_cast<int&>(const_cast<A const &>(*this).get()); };
const int& get() const { return m_someData; };
That is, you should call the const member function from non-const overload, not the other way round. That way, you ensure that even the non-const version doesn't change the state of the object and the code in both functions are indeed same (because you call the const version eventually) — and there would be certainly code duplication which you want to avoid.
If you do this the other way round, the compiler will not tell you if you modify the object in non-const version of the function and it would be incorrect to call such function from const function.
I've got a const method in my class, which cannot be changed to non-const. In this method, I need to call a non-const method but the compiler doesn't let me do that.
Is there any way around it? Here is a simplified sample of my code:
int SomeClass::someMethod() const {
QColor saveColor = color();
setColor(QColor(255,255,255)); // Calling non-const method
// ....
setColor(saveColor); // restore color
return 1;
}
You could use const_cast on this pointer,
int SomeClass::someMethod() const {
const_cast<SomeClass*>( this )->setColor(...);// Calling non-const method
//whatever
}
but if you do that for an object that was originally declared const you run into undefined behavior.
So this:
SomeClass object;
object.someMethod();
is okay, but this:
const SomeClass object;
object.someMethod();
yields undefined behavior.
The real solution is that your const function should not be const in the first place.
One of the challenges of doing const-correctness is you can't do it halfway. It's either all or nothing. If you try to do it halfway, you end up in a tough spot like you are here. You end up with a nice const-correct class being used by some crazy old, typically legacy (or written by an old curmudgeon) code that isn't const-correct and it just doesn't work. You're left wondering if const-correctness is worth all the trouble.
I need to call a non-const method [from a const method]
You can't -- not directly. Nor should you. However, there is an alternative...
Obviously you can't call a non-const method from a const method. Otherwise, const would have no meaning when applied to member functions.
A const member function can change member variables marked mutable, but you've indicated that this is not possible in your case.
You could attempt to cast away constness by doing something like SomeClass* me = const_cast<SomeClass*>(this); but A) This will typically result in UB, or 2) It violates the whole idea of const-correctness.
One thing you could do, if what you're really trying to accomplish would support this, is to create a non-const proxy object, and do nonconst-y stuff with that. To wit:
#include <iostream>
#include <string>
using namespace std;
class Gizmo
{
public:
Gizmo() : n_(42) {};
void Foo() const;
void Bar() { cout << "Bar() : " << n_ << "\n"; }
void SetN(int n) { n_ = n; };
int GetN() const { return n_; }
private:
int n_;
};
void Gizmo::Foo() const
{
// we want to do non-const'y things, so create a proxy...
Gizmo proxy(*this);
int save_n = proxy.GetN();
proxy.SetN(save_n + 1);
proxy.Bar();
proxy.SetN(save_n);
}
int main()
{
Gizmo gizmo;
gizmo.Foo();
}
If you require to change some internal state inside a const-method you can also declare the affected state mutable:
class Foo {
public:
void doStuff() const { bar = 5; }
private:
mutable int bar;
};
This is intended for cases where you have stuff like mutexes as members of your class. Acquiring and releasing a mutex does not affect client-visible state, but is technically forbidden in a const-method. The solution is to mark the mutex mutable. Your case looks similar, although I think your class requires some refactoring for this solution to be applicable.
Also, you might want to read this answer to see how you can make this temporary state-change exception-safe using RAII.
How to call a non-const method from a const method?
You should not. You might run into undefined behaviour if you cast away the const-ness of this, using const_cast. The usage ofconst_cast will shut the compiler's mouth up, but that isn't a solution. If you need to do, then it means the const function should not be const in the first place. Make it non-const.
Or, you should do something else, which would not require you to call non-const function from const function. Like, don't call setColor function? Like, split the const function into more than one functions (if you can do that)? Or something else?
In your particular case, if setColor only sets some member variable, say m_color, then you can declare it mutable:
mutable QColor m_color;
and then set it in your const function, without calling setColor function, and without doing const_cast.
Let's say you have a class
class C
{
int * i;
public:
C(int * v):i(v) {};
void method() const; //this method does not change i
void method(); //this method changes i
}
Now you may want to define const instance of this class
const int * k = whatever;
const C c1(k); //this will fail
but this will fail because of non-const int C's constructor C(int * v)
so you define a const int constructor
C(const int * v):i(v) {}; //this will fail also
But this will fail also since C's member "int * i" is non-const.
What to do in such cases? Use mutable? Casting? Prepare const version of class?
edit: After discussion with Pavel (below) I investigated this problem a bit. To me what C++ does is not correct. Pointer target should be a strict type, that means that you could not for example do the following:
int i;
const int * ptr;
ptr = & i;
In this case language grammar treats const as a promise not to change pointer's target. In addition int * const ptr is a promise not to change pointer value itself. Thus you have two places where const can be applied. Then you may want your class to model a pointer (why not). And here things are falling into pieces. C++ grammar provides const methods which are able to promise not to change field's values itself but there is no grammar to point out that your method will not change targets of your in-class pointers.
A workaround is to define two classes const_C and C for example. It isn't a royal road however. With templates, their partial specializations it's hard not to stuck into a mess. Also all possible arguments variations like const const_C & arg, const C & arg, const_C & arg, C & arg don't look pretty. I really don't know what to do. Use separate classes or const_casts, each way seems to be wrong.
In both cases should I mark methods which don't modify pointer's target as const? Or just follow traditional path that const method doesn't change object's state itself (const method don't care about pointer target). Then in my case all methods would be const, because class is modelling a pointer thus pointer itself is T * const. But clearly some of them modify pointer's target and others do not.
Sounds like you want an object that can wrap either int* (and then behave as non-const), or int const* (and then behave as const). You can't really do it properly with a single class.
In fact, the very notion that const applied to your class should change its semantics like that is wrong - if your class models a pointer or an iterator (if it wraps a pointer, it's likely to be the case), then const applied to it should only mean that it cannot be changed itself, and should not imply anything regarding the value pointed to. You should consider following what STL does for its containers - it's precisely why it has distinct iterator and const_iterator classes, with both being distinct, but the former being implicitly convertible to the latter. As well, in STL, const iterator isn't the same as const_iterator! So just do the same.
[EDIT] Here's a tricky way to maximally reuse code between C and const_C while ensuring const-correctness throughout, and not delving into U.B. (with const_cast):
template<class T, bool IsConst>
struct pointer_to_maybe_const;
template<class T>
struct pointer_to_maybe_const<T, true> { typedef const T* type; };
template<class T>
struct pointer_to_maybe_const<T, false> { typedef T* type; };
template<bool IsConst>
struct C_fields {
typename pointer_to_maybe_const<int, IsConst>::type i;
// repeat for all fields
};
template<class Derived>
class const_C_base {
public:
int method() const { // non-mutating method example
return *self().i;
}
private:
const Derived& self() const { return *static_cast<const Derived*>(this); }
};
template<class Derived>
class C_base : public const_C_base<Derived> {
public:
int method() { // mutating method example
return ++*self().i;
}
private:
Derived& self() { return *static_cast<Derived*>(this); }
};
class const_C : public const_C_base<const_C>, private C_fields<true> {
friend class const_C_base<const_C>;
};
class C : public C_base<C>, private C_fields<false> {
friend class C_base<C>;
};
If you actually have few fields, it may be easier to duplicate them in both classes rather than going for a struct. If there are many, but they are all of the same type, then it is simpler to pass that type as a type parameter directly, and not bother with const wrapper template.
Your example doesn't fail, k is passed by value. The member i is 'implicitly constant' as direct members of C can't be changed when the instance is constant.
Constness says that you can't change members after initialization, but initializing them with values in the initialization list is of course allowed - how else would you give them a value?
What doesn't work is invoking the constructor without making it public though ;)
update addressing updated question:
Yes, C++ forces you into some verboseness sometimes, but const correctness is a common standard behaviour that you can't just redefine without breaking expectations. Pavels answer already explains one common idiom, which is used in proven libraries like the STL, for working around this situation.
Sometimes you have to just accept that languages have limitations and still deal with the expectations of the users of the interface, even if that means applying an apparently sub-optimal solution.
Your question does not make sense. Where did you get all these "this will fail" predictions? None of them are even remotely true.
Firstly, it is completely irrelevant whether the constructor's parameter is declared const or not. When you are passing by value (as in your case) you can pass a const object as an argument in any case, regardless of whether the parameter is declared as const or not.
Secondly, from the constructor's point of view, the object is NOT constant. Regardless of what kind of object you are constructing (constant or not), from within the constructor the object is never constant. So there's no need for mutable or anything.
Why don't you just try compiling your code (to see that nothing will fail), instead of making strange ungrounded predictions that something "will fail"?
A const int* is not the same as a int* const. When your class is const, you have the latter (constant pointer to mutable integer). What you're passing is the former (mutable pointer to constant integer). The two are not interchangeable, for obvious reasons.
When you instantiate
const C c1(...)
Because c1 is const, its member i turns in to:
int* const i;
As someone else mentioned, this is called implicit const.
Now, later in your example, you attempt to pass a const int*. So your constructor is basically doing this:
const int* whatever = ...;
int* const i = whatever; // error
The reason you get an error is because you can't cast const to non-const. The 'whatever' pointer is not allowed to change the thing it points to (the int part is const). The 'i' pointer is allowed to change what it points to, but cannot itself be changed (the pointer part is const).
You also mention wanting your class to model a pointer. The STL does this with iterators. The model some implementations use is having a class called 'const_iterator' which hides the real pointer and only supplies const methods to access the pointed-to data. Then there's also an 'iterator' class which inherits from 'const_iterator', adding non-const overloads. This works nicely - it's a custom class which allows the same constness as pointers, where the types mirror pointers like so:
iterator -> T*
const iterator -> T* const
const_iterator -> const T*
const const_iterator -> const T* const
Hopefully that makes sense :)
OK here's what I have done so far. To allow inheritance after const version of class without const_casts or additional space overhead I created an union which basically looks like ths:
template <typename T>
union MutatedPtr
{
protected:
const T * const_ptr;
T * ptr;
public:
/**
* Conversion constructor.
* #param ptr pointer.
*/
MutatedPtr(const T * ptr): const_ptr(ptr) {};
/**
* Conversion to T *.
*/
operator T *() {return ptr;}
/**
* Conversion to const T *.
*/
operator const T *() const {return const_ptr;}
};
When MutatedPtr field is declared, it ends up so that in const methods const_ptr is returned, while non-const ones get plain ptr. It delegates method's const-ness to pointer target which makes sense in my case.
Any comments?
BTW you can of course do similar thing with non-pointer types or even methods, so it looks that introducing mutable keyword wasn't necessary(?)
I've run into the same unfortunate issue and after lamenting the lack of a const constructor in C++ I've come to the conclusion that two templatization is the best course, at least in terms of reuse.
A very simplified version of my case/solution is:
template< typename DataPtrT >
struct BaseImage
{
BaseImage( const DataPtrT & data ) : m_data( data ) {}
DataPtrT getData() { return m_data; } // notice that if DataPtrT is const
// internally, this will return
// the same const type
DataPtrT m_data;
};
template< typename DataPtrT >
struct DerivedImage : public BaseImage<DataPtrT>
{
};
There is a very unfortunate loss of class inheritance but in my case it was acceptable to make a sort of casting operator to be able to cast between const and non-const types with some explicit knowledge of how to do the conversion under the hood. That mixed with some appropriate use of copy constructors and/or overloaded dereference operator might get you to where you want to be.
template< typename OutTypeT, typename inTypeT )
image_cast< shared_ptr<OutTypeT> >( const shared_ptr<InTypeT> & inImage )
{
return shared_ptr<OutTypeT>( new OutTypeT( inImage->getData() ) );
}