Reputation: 579
I want to insert some elements to the list.
What I really want to do is to use "insert3" because it guarantee that the pointer won't change, and the data won't change.
But "insert2" and "insert3" give the following error, which "insert1" doesn't:
class A
{
public:
std::list<int*> l;
void insert(int* const a)
{
l.push_back(a); //works
}
void insert2(const int* a)
{
l.push_back(a);
/*
no instance of overloaded function "std::list<_Ty, _Ax>::push_back [with _Ty=int *, _Ax=std::allocator<int *>]"
matches the argument list
*/
}
void insert3(const int* const a)
{
l.push_back(a);
}
};
Thanks for your help!
Upvotes: 2
Views: 3393
Reputation: 320571
It is one of the typical higher-level "issues" with C++-style compile-time const-correctness type system.
If you want to store int *
pointers in your list, then you will not be able to add const int *
pointers to that list (for obvious reasons). This will allso force all your insert
methods to accept int *
pointers, not const int *
pointers.
I understand, that what you really want to express is that insert
method itself does not change the pointed data (and it doesn't). However, as you can see, insert
has some far-reaching side-effects - it stores the pointer in a list. This would potentially violate the const-correctenss if insert
accepted const int *
pointers.
In other words, it is not enough to consider what insert
is doing by itself, it is also important to consider what possibilities insert
opens to other code (in this case - to other code that has access to the same list). And in your case the possibilities it opens would easily allow const-correcness violations in other code if your insert
quietly accepted const int *
pointers.
You can, of course, impose your own vision of proper const-correctness in this case by using forceful const_cast
s. But it won't look pretty.
Upvotes: 1
Reputation: 11126
You should use a list<int const* const>
as the type of l
instead and then you can use any of your inserts including insert3
.
By inserting into a list<int*>
you attempt to convert your int const*
(pointer to const int) to an int*
(pointer to int).
Since you are removing the guarantee that you will not edit the target of the pointer, this is not implicitly doable. You may use a const_cast
(or c-cast) if you really wish to do this, but usually casting away const
-ness is a very bad idea (tm).
const
won't change a thingIf you use version 3 using an int const* const
(const pointer to const int), you are not getting anything more or less than the guarantee that the variable a
will not be changed while insert3
is running. By inserting the pointer into your list, you are actually copying it. This means that no matter whether a
is const
or not, your resulting list item will be the type you specified in the beginning.
By making the list into list<int const* const>
you ensure that any pointer inserted cannot be changed later on, and the value pointed to it can only be changed after explicitly getting rid of the const
ness of your pointer. Inserting into it is possible, since adding const
is always implicitly possible
Upvotes: 2
Reputation: 96810
Change the list
to take a pointer to const
:
std::list<const int*> l;
Since you had a pointer to const
for the parameter, taking away its const
-ness through an implicit conversion wouldn't be allowed.
Upvotes: 1