上下文:尝试在模板化的自制shared_ptr上实现copy and swap惯用法。我无法调用此函数:
template<typename U>
shared_ptr<T>& operator=(shared_ptr<U> rhs)
{
static_assert(std::is_base_of<T, U>::value);
swap(*this, rhs);
return *this;
}
从不必要的代码中剥离代码:
以下代码无法编译。 &#34; x = y&#34; line是尝试使用:
foo<T>& operator=(const foo<U>& ptr) = delete;
如果我删除/评论已删除的功能行。意思是如果我没有定义它们,编译器将为我做,代码将编译。但是,编译器生成的特殊成员将优先于我的运算符,而不会被调用。
template<typename T>
class foo
{
public:
// copy&swap
template<typename U>
foo<T>& operator=(foo<U> rhs)
{
// whatever is needed swap and all
return *this;
}
template<typename U>
foo<T>& operator=(const foo<U>& ptr) = delete;
template<typename U>
foo<T>& operator=(foo<U>&& ptr) = delete;
foo<T>& operator=(foo<T>&& ptr) = delete;
};
int main()
{
foo<int> x,y;
x = y;
return 0;
}
问题:
修改/应答
到目前为止,这是正确的版本:
代码:
#include <iostream>
template<typename T>
class foo
{
private:
template <typename U> friend class foo;
template<typename U>
void assign(const foo<U>& other)
{
static_assert(std::is_base_of<T, U>::value || std::is_convertible<U, T>::value);
std::cout << "templated assign function" << std::endl;
this->data = other.data;
}
template<typename U>
void move(foo<U>&& other)
{
static_assert(std::is_base_of<T, U>::value || std::is_convertible<U, T>::value);
std::cout << "templated move function" << std::endl;
this->swap(*this, other);
}
public:
template<class X, class Y> void swap(foo<X>& left, foo<Y>& right) noexcept
{
std::cout << "templated swap function" << std::endl;
std::swap(left.data, right.data);
}
void swap(foo<T>& left, foo<T>& right) noexcept
{
std::cout << "swap function" << std::endl;
std::swap(left.data, right.data);
}
foo() {}
explicit foo(foo<T>&& other)
{
std::cout << "move constructor foo(foo&& other)" << std::endl;
move(std::forward<decltype(other)>(other));
}
explicit foo(const foo<T>& other)
{
std::cout << "copy constructor foo(const foo& other)" << std::endl;
assign(std::forward<decltype(other)>(other));
}
template<typename U>
foo(foo<U>&& other)
{
static_assert(std::is_base_of<T, U>::value || std::is_convertible<U, T>::value);
std::cout << "templated move constructor template<typename U> foo(foo<U>&& other)" << std::endl;
move(std::forward<decltype(other)>(other));
}
template<typename U>
foo(const foo<U>& other)
{
static_assert(std::is_base_of<T, U>::value || std::is_convertible<U,T>::value);
std::cout << "templated copy constructor template<typename U> foo(const foo<U>& other)" << std::endl;
assign(std::forward<decltype(other)>(other));
}
// copy&swap
template<typename U>
foo<T>& operator=(foo<U> rhs)
{
static_assert(std::is_base_of<T, U>::value || std::is_convertible<U, T>::value);
std::cout << "templated assignement template<typename U> foo<T>& operator=(foo<U> rhs)" << std::endl;
auto tmp = rhs.data;
rhs.data = reinterpret_cast<U*>(data);
data = reinterpret_cast<T*>(tmp);
return *this;
}
foo<T>& operator=(foo<T> rhs)
{
std::cout << "assignement foo<T>& operator=(foo<T> rhs)" << std::endl;
std::swap(rhs.data,data);
return *this;
}
private:
T * data;
};
int main()
{
foo<int> x,y;
const foo<int>& cy = y;
foo<short> z, w;
x = y;
x = cy;
x = std::move(y);
x = z;
x = std::move(w);
return 0;
}
答案 0 :(得分:1)
operator=(const foo&)
仅在cv限定符中有所不同,并且将首选来自模板= delete
导致operator=(const foo&)
被禁止。它不仅阻止编译器生成它。这应该这样做:
#include <tuple>
#include <iostream>
template<typename T>
class foo
{
private:
template <typename U> friend class foo;
foo& assign(T rhs)
{
std::swap(data, rhs);
return *this;
}
public:
template<typename U>
foo& operator=(const foo<U>& rhs)
{
return assign(rhs.data);
}
template<typename U>
foo& operator=(foo<U>&& rhs)
{
return assign(std::move(rhs.data));
}
foo& operator=(const foo& rhs)
{
return assign(rhs.data);
}
foo& operator=(foo&& rhs)
{
return assign(std::move(rhs.data));
}
private:
T data;
};
int main()
{
foo<int> x,y;
const foo<int>& cy = y;
foo<short> z, w;
x = y;
x = cy;
x = std::move(y);
x = z;
x = std::move(w);
return 0;
}
编辑1:添加了成员并致电交换。
修改2:更改了分配,以按值T
取代foo<T>
添加移动分配
注意:在分配T
不同类型(foo
)时,现在使用U
的转换构造函数