Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking if a variable is constant qualified

I was reading about const_cast and it seemed unsafe and not very helpful. The best answer about it in SO states the it would be useful in a scenario like this:

void func(const char* param, bool modify){
    if(modify)
        //const_cast and change param
    // stuff that do not change param
}

Although this a possible use, it has its risks because you have to correctly provide the value of "modify", or else you will get an undefined behaviour since you are changing something that was supposed to be constant. I wonder if you could achieve the same functionality without having to supply this extra argument and for that you would most likely need to check the existence of a const qualifier.

The closes thing I found was the std function is_const, but it seems to be limited to a different kind of usage:

is_const<const int>::value //returns true
is_const<int>::value // returns false
const int myVar=1;
is_const<myVar>::value // what it would look like ( does not compile)

I've also tried using similar function signatures that only differ by a "const" qualifier, but that is perceived as a redefinition. So is it possible at all to do it? If so, how can it be done?

like image 635
guivenca Avatar asked Dec 18 '22 23:12

guivenca


2 Answers

You can use std::is_const<decltype(myVar)>::value to check whether myVar has been declared as const.

However, if myVar is a pointer or a reference to another object, there is no way of knowing if that object is const or not from inside the function.

like image 147
Quentin Avatar answered Jan 10 '23 20:01

Quentin


For this case, I think you can just use two overloads of the function:

#include <stdio.h>

void func(const char* param) {
    printf("Not modifying %c\n", param[0]);
}

void func(char* param) {
    printf("Modifying %c\n", param[0]);
    func(const_cast<const char*>(param));
}

int main() {
    const char foo[1] = {'F'};
    char bar[1] = {'B'};

    func(foo);
    func(bar);
}

Which outputs:

Not modifying F
Modifying B
Not modifying B

When calling func, the right overload is automatically selected based on the const-ness of the argument. Here, I let the non-const version call the const version to do the non-const part of the work, which seemed to fit the original usecase, but you can of course also let both of these call a third (possibly private/static) version that takes a bool modify parameter as original suggested, but now in the knowledge that the constness is correct).

Alternatively, if you want to use std::is_const, you can use a template function to autogenerate versions for const and non-const and automatically deduct the modify parameter:

#include <stdio.h>
#include <type_traits>

static void func(char* param, bool modify) {
    if (modify)
        printf("Modifying %c\n", param[0]);
    printf("Not modifying %c\n", param[0]);
}

template<typename T>
void func(T *param) {
    func(const_cast<char*>(param), !std::is_const<T>::value);
}

With the same main() as in the first example, this produces exactly the same output as the first example.

like image 20
Matthijs Kooijman Avatar answered Jan 10 '23 19:01

Matthijs Kooijman