2015-04-03 52 views
0

我想实现一类的运算符重载,如:避免在模板类方法隐式转换

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 

它甚至有可能做到这一点?

+1

也许这些? http://stackoverflow.com/questions/12877546/how-do-i-avoid-implicit-casting-on-non-constructing-functions-c http://stackoverflow.com/questions/9458741/with-显式删除的成员函数在C11是它仍然值得INN – Salmonstrikes 2015-04-03 03:12:06

+0

@Salmonstrikes否,因为他们只适用于单个函数(而不是_class_方法),它们是特定类型的专业化,不是所有类型 – rev 2015-04-03 03:14:04

+0

鲑鱼的链接的第一个给你想要的 – 2015-04-03 03:18:26

回答

2

正如意见建议,使该除了一个类型匹配一切delete d模板函数你想允许:

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 
} 

如果你打算做这个有很多,你可以卸载重型提升到帮手类:

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; 
    } 
}; 
+0

注意,你不需要在课堂内写'A ',只需'A' – 2015-04-03 03:23:02

+0

令人惊讶的是,我只是改变了'= delete;'到' {static_assert(false,“[...] error [...]”); }'。你能解释为什么第二个函数被调用而不是第一个函数? – rev 2015-04-03 03:27:09

+1

@AcidShout [see here](http://stackoverflow.com/questions/29324762/why-is-template-overload-a-better-match-than-a-simple-conversion)解释那 – 2015-04-03 03:35:35