guivenca
guivenca

Reputation: 179

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?

Upvotes: 7

Views: 5268

Answers (2)

Matthijs Kooijman
Matthijs Kooijman

Reputation: 2797

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.

Upvotes: 1

Quentin
Quentin

Reputation: 63124

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.

Upvotes: 13

Related Questions