我正在为具有克隆功能的类编写一个继承自
std::unique_ptr
的类:
template <typename T>
class cl_ptr : public std::unique_ptr<T>
{
public:
cl_ptr() noexcept = default;
cl_ptr(T* p) noexcept : std::unique_ptr<T>(p) {}
cl_ptr(cl_ptr<T> const& cp) : std::unique_ptr<T>(cp ? cp->clone() : nullptr) {}
cl_ptr(cl_ptr<T>&&) noexcept = default;
cl_ptr<T>& operator=(cl_ptr<T> const& cp) { this->reset(cp ? cp->clone() : nullptr); return *this; }
cl_ptr<T>& operator=(cl_ptr<T>&& cp) noexcept = default;
~cl_ptr() noexcept = default;
};
当我尝试从类型为
T
的实例转换为类型为 T const
的实例时出现错误:
cl_ptr<Foo> p1(new Foo);
cl_ptr<Foo const> p2 = p1; // <- Compiler error here
// error: conversion from ‘cl_ptr<Foo>’ to non-scalar type ‘cl_ptr<const Foo>’ requested
但是我不知道如何实现它。
当然我不希望这段代码编译:
cl_ptr<Foo const> p1(new Foo);
cl_ptr<Foo> p2 = p1; // <- Always wrong
最小可重现示例:
# include <memory>
template <typename T>
class cl_ptr : public std::unique_ptr<T>
{
public:
cl_ptr() noexcept = default;
cl_ptr(T* p) noexcept : std::unique_ptr<T>(p) {}
cl_ptr(cl_ptr<T> const& cp) : std::unique_ptr<T>(cp ? cp->clone() : nullptr) {}
cl_ptr(cl_ptr<T>&&) noexcept = default;
cl_ptr<T>& operator=(cl_ptr<T> const& cp) { this->reset(cp ? cp->clone() : nullptr); return *this; }
cl_ptr<T>& operator=(cl_ptr<T>&& cp) noexcept = default;
~cl_ptr() noexcept = default;
};
class Foo
{
public:
Foo() = default;
Foo(Foo const&) = default;
~Foo() noexcept = default;
Foo* clone() const { return new Foo(*this); }
};
int main()
{
cl_ptr<Foo> p1(new Foo);
cl_ptr<Foo const> p2 = p1;
cl_ptr<Foo> p3 = p2; // must fail
return 0;
}
一般来说:你不能。由于模板专业化,
A<B const>
和A<B>
可能是完全不同的东西。因此,一般来说,具有不同模板参数列表的类模板实例被视为不同的、不相关的类型。
对于智能指针,标准库竭尽全力在某些情况下启用此类转换,但这些都是相应类模板的自定义实现。您
可以为您的特定班级做同样的事情。但是 cl_ptr
似乎是
std::unique_ptr
的一个简单包装,所以为什么不直接使用
std::unique_ptr
呢?