Reputation: 1988
I have a vector that looks like this.
std::vector<std::pair<int,int> > v;
and I want to pass it into a function and make it so it's constant.
first I tried
void fun(const std::vector<std::pair<int,int> > v)
but that function allowed me to have the line
std::pair<int,int> p = v[i];
which I thought should have thrown an error since pair is not of type const. Then I realized that it's only the pointers that are being declared constant in vector so I tried
void fun(const std::vector<const std::pair<int,int> > v)
but that throws the error about there being no conversion.
I'm sure there's some inner workings that I'm not understanding that makes this illegal but would love some insight. Thanks.
Upvotes: 3
Views: 1135
Reputation: 31
void fun(const std::vector<std::pair<int,int> > v)
{
////
std::pair<int,int> p = v[i];
}
https://en.cppreference.com/w/cpp/container/vector/operator_at
No error will happen here because std::vector has overloaded operator[]
both for const and non-const instances. In your case it will be resolved to const version and return const &
to underlying i
element.
Consider following code:
void fun(const std::vector<std::pair<int,int> > v)
{
////
std::pair<int,int> p = v[i]; //OK
v[i] = std::pair<int,int>{10,20}; //Compile error, trying to modify const data!
}
Upvotes: 1
Reputation: 38295
I think you confuse reference and value semantics here. Lets the first function signature you tested:
void fun(const std::vector<std::pair<int,int> > v)
This copies the function argument into a new object v
, which is additionaly const
-qualified. Such signatures seldomly make sense: either you want to pass it as a const
reference (to avoid copying) or you want to pass it by non-const
value, because the function body will mutate the argument, but shall operate on its only copy. Besides, this snippet:
std::pair<int,int> p = v[i];
compiles just fine with the above function signature, because it copies the vector element at position i
into a new pair
object. The latter can be mutated, but this doesn't affect the vector at all.
Let's now consider the second function signature:
void fun(const std::vector<const std::pair<int,int> > v)
The same as before still applies here, and in addition, std::vector<const T>
isn't useful, see this thread for an explanation.
How to fix it? If you don't want to copy the argument, but the function doesn't modify the vector, pass it by const
reference. If the function modifies the vector and these modifications shall be visible at the call side, pass it as non-const
reference. If the function modifies the vector but that shall happen independently of the call side vector, pass by non-const
value.
Upvotes: 4