避免对模板化 class 方法进行隐式转换

Avoid implicit casting on templated class methods

我正在尝试为 class 实现运算符重载,例如:

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

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

所以我能做到:

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

这很好用。

但是,如果我这样做:

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

它仍然有效!我能以某种方式阻止它吗?

我试过像这样标记过载 explicit

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

但是我得到一个错误:

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

甚至可以这样做吗?

按照评论中的建议,制作一个 deleted 模板函数,匹配除您要允许的一种类型之外的所有内容:

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
}

如果您要经常这样做,可以将繁重的工作交给帮手 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;
    }
};