考虑以下自包含代码。
#include <iostream>
template<typename Ty>
class Foo {
private:
Ty m_data;
public:
Foo() :m_data() {}
Foo(Ty data) :m_data(data) {}
template<typename U>
Foo& operator=(Foo<U> rv)
{
m_data = rv.m_data;
return *this;
}
private:
Foo(Foo&);
Foo& operator=(Foo&);
};
int main()
{
Foo<int> na(10);
Foo<int> nb;
nb = Foo<int>(10); // (1)
Foo<int>(10); // (2)
}
我的理解是声明(1)是一个赋值而不是复制COnstructor。然而,在编译(VC ++和G ++)时,错误消息指出,它尝试匹配被声明为私有的复制构造函数。
1>Source.cpp(23): error C2248: 'Foo<int>::Foo' : cannot access private member declared in class 'Foo<int>'
1> Source.cpp(16) : see declaration of 'Foo<int>::Foo'
我的问题是,为什么它会尝试搜索复制构造函数而不是分配。
注意,我知道失败的分配是因为(2)编译没有任何错误。
答案 0 :(得分:4)
您的赋值运算符按值获取其参数,这需要复制。该副本可能(或可能不)被删除 - 但复制构造函数仍需要可用且可访问,即使未被调用。
答案 1 :(得分:3)
有两个问题:
Foo& operator=(Foo&);
采用非常量左值引用。这意味着它不能被选为nb = Foo<int>(10);
中的重载,因为RHS是一个右值如果您修复1.以获取const
引用,则gcc会出现以下错误:
错误:&#39; Foo&amp; Foo :: operator =(const Foo&amp;)[with Ty = int]&#39;是私人的
如果你修复了2.所以模板赋值运算符采用const
引用,代码编译时没有错误。
答案 2 :(得分:0)
您的赋值运算符按值传递参数,因此它使用copy ctor:
template<typename U>
Foo& operator=(Foo<U> rv)
通过const引用传递它的可能解决方案:
template<typename U>
Foo& operator=(const Foo<U> &rv)
答案 3 :(得分:-1)
私人版
private:
Foo(Foo&);
Foo& operator=(Foo&);
无法调用,因为它采用非常量左值引用,所以
Foo& operator=(Foo<U> rv)
调用此版本但它需要参数按值,并且必须调用复制构造函数。