原文地址 https://segmentfault.com/a/1190000004467381
最近被一个语法问题缠了半天,终于找到了原因。不仔细思考一下写的时候真的很容易忽略。先看代码:
template class A { public: const T t = 0;
template A& operator=(const A& a) { return *this; } };
int main() { A a, b;
b = a; // error } 这会带来一个编译错误,然而横睇掂睇都看不出问题。于是我就试了一下这样的代码:A c; b = c;居然通过了编译。F**k,这个模板居然胳膊肘往外拐。
其实我在写这个代码的时候忽略了一点,就是default assignment operator,它是你在定义类的时候编译器默认给你加上去的,行为是对所有成员变量赋值。它的声明是A& operator=(const A& a);,跟我们自己定义的放在一起:
template A& operator=(const A& a) { return *this; }
A& operator=(const A& a) /= delete/; 恰好构成了模板特化,这就糟了。一旦构成了特化,OtherT可以匹配的类型就会除去int,用A赋值时只能调用系统给我们定义的那个。然而它也不起作用,因为成员里面有常量(这样它就会被标记为= delete,留意delete并不会令OtherT可以匹配到int,反而令它匹配不到)。
知道了原因之后,解决就很方便了,只要重新定义这个默认赋值运算符就好:
A& operator=(const A& a) { /…/ }