我正在编写一个继承自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;
};
当我尝试从 type 的实例转换T
为 type 的实例时出现错误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
直接使用呢?我将允许任何从to转换
cl_ptr<T>
到的cl_ptr<U>
地方的转换,就像. 这允许和不允许,但也包括等等。T *
U *
std::unique_ptr
T *
const T *
const T *
T *
Derived *
Base *