Re: std::auto_ptr and const correctness
jens.muaddib wrote:
On 14 Mai, 11:10, SG <s.gesem...@gmail.com> wrote:
[...]
I don't think there's a universal right and wrong here. You have to
pick some default semantics and provide a mechanism to override it. In
the D programming language the default is a "deep const". It actually
makes sense because object members are not really members but
references. And sometimes you don't want "deep constness" which is why
D has the keyword "mutable". In C++ you have *real* object members
(composition) so this "deep constness" is not as important as it is in
D.
There are basically 3 cases in C++ regarding members and constness:
(1) An object is is logically and actually a member (composition)
(2) An object is logically a member but only referenced via a pointer
(3) An object is neither logically nor physically a member
Only the 2nd case requires you to manually protect your "logical
member objects" by making the pointers private and providing
appropriate const-overloaded member functions (example: std::vector,
its dynamically allocated array and const-overloaded operator[]
functions). The "shallow const" is okay in cases 1 and 3.
I like the D way because it makes sense to treat logically composed
object and really composed object in the same way. And in C++, there
is also a mutable keyword, so I wonder why the committee has not
defined pointers in const member functions as const T* const. Maybe
mutable was introduced too late and they didn't want to break
compatibility.
You're asking for a special-case rule, when looked at more generally.
First, what you're proposing:
struct X { int* p; };
void f( X& m, X const& c )
{
*m.p = 0; // OK
*c.p = 0; // error, since p is of type int const* const
}
Now, what if I was doing this:
struct Y { int i; };
int a [10];
void g( Y& m, Y const& c )
{
a [m.i] = 0; // OK
a [c.i] = 0; // should this be an error too?
}
In both cases, the member of the struct is effectively a pointer into
something else, and in both cases used to modify what it "pointed" to. So
I call the rule special-case because it flags the first but not the
second.
And as a reminder, you can get the first behavior by simply defining your
own const_propagating_pointer class template. You can probably even have
it propagate const multiple levels, so that a const
const_propagating_pointer<int**> will look like an int const* const*.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]