rev
rev

Reputation: 1861

Avoid implicit casting on templated class methods

I'm trying to implement an operator overload for a class such as:

template<class T> class A{
public:
    T val;

    A<T>& operator=(const T& v) {
        this->val = v;
        return *this;
    }
}

So I can do:

A<bool> obj;
obj = true; // instead of obj.val = true
obj = false;

This works fine.

However, if I do this:

A<bool> obj;
obj = 123123; // bool is not a number!

It still works! Can I somehow prevent that?

I tried marking the overload explicit like this:

explicit A<T>& operator=(const T& v) { ... }

but I get an error:

error C2071: 'A<T>::operator =': illegal storage class

Is it even possible to do this?

Upvotes: 0

Views: 81

Answers (1)

M.M
M.M

Reputation: 141618

As suggested in comments, make a deleted template function that matches everything except the one type you want to allow:

template<class T> class A
{
public:
    T val;

    A & operator=(T const &v) {
        val = v;
        return *this;
    }

    template<class U>
    A & operator=(U const &v) = delete;
};

int main()
{
    A<bool> a;
    a = true;
    a = 1;        // error: use of deleted function
}

If you are going to do this a lot, you can offload the heavy lifting to a helper class:

template<typename T>
struct exact
{
    T const &t;
    exact(T const &t): t(t) {}

    template<typename U> 
    exact(U u) = delete;
};

template<class T> class A
{
public:
    T val;

    A &operator=(exact<T> v) {
        val = v.t;
        return *this;
    }
};

Upvotes: 2

Related Questions