2

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;

}
Albert G Lieu
  • 891
  • 8
  • 16
  • You can force the language's hand, but you can't modify constant data. – chris Feb 06 '22 at 05:20
  • @RetiredNinja given the fact that I can only add code to body of ````func````, can I still remove the const? Yes , I know we can pass arr by a copy to ````fun```` – Albert G Lieu Feb 06 '22 at 05:22
  • Since you edited the code to pass by const reference instead of value then you should just make a copy inside the function. – Retired Ninja Feb 06 '22 at 05:27
  • Change the declaration of your function parameter. `void func(vector& arr)` – Martin York Feb 06 '22 at 05:39
  • Do you ask, if it is possible to do an out-of-place sort, which reads from a const vector and writes in new memory, more efficiently than a copy of the vector and then in-place sort? – Sebastian Feb 06 '22 at 06:26

3 Answers3

3

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.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • It's not UB to cast away const so long as you don't modify the obj. Note that the contents of vector are not const and can be modified by casting away const. What you can't do is modify the obj by, for instance, `push_back()` – doug Nov 28 '22 at 02:19
2

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.

viraltaco_
  • 814
  • 5
  • 14
  • ````You should never attempt to modify a const variable````, I will take your words for it, but if const variable should never be changed, then what is the point of have ````const_cast```` in c++? – Albert G Lieu Feb 06 '22 at 17:52
  • @AlbertGLieu `then what is the point of have const_cast in c++?` See my edited answer. – eerorika Feb 06 '22 at 18:06
0

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

doug
  • 3,840
  • 1
  • 14
  • 18