从右值引用和const引用中编写重载函数时,可能会有代码重复,因此我有时会使用相同的代码。如下图所示:
#include <iostream>
#include <type_traits>
struct A {
template <typename T>
A& operator=(T&&) {
if constexpr (::std::is_rvalue_reference_v<T&&>) {
::std::cerr << "operator= move\n";
} else {
::std::cerr << "operator= copy\n";
}
return *this;
};
};
现在我的理解是,这应该实现A& operator=(T const&)
和A& operator=(T&&)
。所以给定这段代码,理论上我会期待这个调用:
int main() {
A a,b;
a = b;
a = ::std::move(b);
}
产生以下输出:
operator= copy
operator= move
然而,令我惊讶的是,第二行(!)丢失了。我怎样才能同时覆盖这两个?
我正在使用g ++ 8.3.0和-std=c++17
进行编译。
鉴于1201ProgramAlarm指出的解释,有趣的问题是为什么它适用于任何一种情况。答案很简单:你分配了一个非const
对象,所以T
被推断为A&
(并且T&&
也变成了A&
),产生了比接受const A&
的隐式复制构造函数严格更好的匹配。对于移动构造函数,或者如果您分配了const A
,则签名是相同的,在这种情况下,首选非模板。