Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forcing class instances to be const

Tags:

c++

Is there any way to force to only allow const instances of class to be instantiated, and have non-const instances be detected as an error by the compiler?

like image 653
Danra Avatar asked Feb 28 '26 22:02

Danra


1 Answers

is there any generic way to take an existing class, and "constify" it by removing all non-const functionality?

One possible workaround is to create a wrapper class that holds an instance of the class and only gives access to a const reference to it.

template<class T>
class Immutable {
public:
    template<typename... Args>
    Immutable(Args&&... args) : instance(forward<Args>(args)...) {
    }
    operator const T&() {
        return instance;
    }
    const T& get() const {
        return instance;
    }
private:
    Immutable& operator=(const Immutable& other) = delete;
    T instance;
};

Suppose you have a mutable class Class:

class Class {
public:
    Class() : m_value(0) {
    }
    Class(const Class& other) : m_value(other.m_value) {
    }
    Class(int value) : m_value(value) {
    }
    Class(int x, int y) : m_value(x + y) {
    }
    void change(int value) {
        m_value = value;
    }
    int value() const {
        return m_value;
    }
private:
    int m_value;
};

Here is how Immutable<Class> can be used:

void functionTakingConstReference(const Class& x) {
}

void functionTakingNonConstReference(Class& x) {
}

void functionTakingImmutableClass(Immutable<Class>& x) {
}

void functionTakingValue(Class x) {
}


int main(int argc, char *argv[])
{
    // Any constructor of Class can also be used with Immutable<Class>.
    Immutable<Class> a;
    Immutable<Class> b(1);
    Immutable<Class> c(2, 3);
    Immutable<Class> d(c);

    // Compiles and works as expected.
    functionTakingConstReference(a);
    functionTakingImmutableClass(a);
    functionTakingValue(a);
    cout << a.get().value() << endl;

    // Doesn't compile because operator= is deleted.
    // b = a;


    // Doesn't compile because "change" is a non-const method.
    // a.get().change(4);


    // Doesn't compile because the function takes a non-const reference to Class as an argument.
    // functionTakingNonConstReference(a);

    return 0;
}
like image 149
Anton Avatar answered Mar 02 '26 15:03

Anton



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!