remove const qualifier of vector in c++

2.7k Views Asked by At

Is it possible to remove constness of vector ? If so, how can it be achieved? For some reason, I don't have access to the main (), can I still remove the constness of arr in the following code snipet? It feels like that auto arr0 = const_cast<vector<int> & > (arr); is identical to vector<int> arr0 = arr;. I guess it is just an example of explicit vs implicit cast,which both creates a copy of original array ````arr```. Is it possible to remove constness inplace without creating a copy?

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;


vector<int> func(const vector<int>& arr){
//    vector<int> arr0 = arr;
    auto arr0 = const_cast<vector<int> & > (arr);
    sort(arr0.begin(), arr0.end());
    return arr0;
}

int main(){
    const vector<int> arr = {3,4,1,5,2};
    auto res = func(arr);
    for (auto n:res)
        cout<<n<<" ";
    return 0;

}
3

There are 3 best solutions below

1
eerorika On

Don't attempt to cast away constness. Modifing a const object will result in undefined behaviour.

It feels like that auto arr0 = const_cast<vector<int> & > (arr); is identical to vector<int> arr0 = arr;

It is effectively the same. The cast is redundant.

Is it possible to remove constness inplace without creating a copy?

If you wish to sort a vector without making a copy, then don't make the vector const in the first place. If it is const, then you cannot modify it.

then what is the point of have const_cast in c++?

It's rarely needed, but there are a few use cases.

You can use it to convert a non-const glvalue expression into a const one:

void fun(T&);       // overload 1
void fun(const T&); // overload 2
T t;
fun(t);                       // calls 1
fun(const_cast<const T&>(t)); // calls 2

If you have a provably non-const object, and a const reference referring to the non-const object, then you can cast away constness of the reference:

T t;
const T& ref = t;
const_cast<T&>(ref) = new_value;

Same cases apply to volatile qualifier, although that's even more rarely needed.

2
viraltaco_ On

You can make a copy, it achieves what you're already trying to do. (You get return value optimization, too).

#include <vector>
#include <algorithm>

template <class T>
static std::vector<T> func(std::vector<T> v) {
  std::sort(v.begin(), v.end());
  return v;
}

Live Example
You should never attempt to modify a const variable, that's undefined behavior, it doesn't have to do anything, and whatever it does is up to the compiler.

0
doug On

Your example is fine. And there is no need to make a copy. There is no undefined behavior. Here's why. This declares arr as a top level const. You may not modify the object without UB. However, the object that is const does not include the dynamic memory contents. In fact the contents are not even allowed to be declared const.

const vector<int> arr = {3,4,1,5,2};

You are allowed to cast away constness so long as you don't alter/write to the const arr object. Calling v.begin() and v.end() does not alter the arr object hence is not undefined behavior. I explored this here

This is not UB and sorts arr inline.

void func(const vector<int>& arr){
    auto& arr0 = const_cast<vector<int> & > (arr);
    sort(arr0.begin(), arr0.end());
}

Here's an example of the code in a constexpr function:

#include <vector>
#include <algorithm>

consteval int foo()
{
    const std::vector<int> a = { 1,2,3 };
    auto& v = const_cast<std::vector<int>&>(a);
    v[0] = 42;
    std::sort(v.begin(), v.end());
    return a[2];
}

int main()
{
    return foo();  // returns 42 since sorted
}

Compiler Explorer