为什么我自己实现的unique_ptr没有提供call operator?
Why my unique_ptr realized by myself does not provide a call operator?
首先我自己实现unique_ptr:
namespace mcj {
template <typename CallbackT>
class unique_ptr {
public:
unique_ptr(CallbackT* ptr = nullptr) : ptr_(ptr) {}
template <
typename CallbackT1,
typename = typename std::enable_if<
std::is_convertible<CallbackT1*, CallbackT*>::value>::type>
unique_ptr(unique_ptr<CallbackT1>&& ptr) {
ptr_ = ptr.release();
}
unique_ptr(unique_ptr<CallbackT>&& ptr) {
if (ptr_) {
delete ptr_;
ptr_ = nullptr;
}
ptr_ = ptr.release();
}
template <
typename CallbackT1,
typename = typename std::enable_if<
std::is_convertible<CallbackT1*, CallbackT*>::value>::type>
unique_ptr<CallbackT>& operator=(unique_ptr<CallbackT1>&& ptr) {
ptr_ = ptr.release();
}
unique_ptr<CallbackT>& operator=(unique_ptr<CallbackT>&& ptr) {
if (ptr_) {
delete ptr_;
ptr_ = nullptr;
}
ptr_ = ptr.release();
return *this;
}
unique_ptr(const unique_ptr<CallbackT>& other) = delete;
unique_ptr<CallbackT>& operator=(const unique_ptr<CallbackT>& other) = delete;
~unique_ptr() {
delete ptr_;
ptr_ = nullptr;
}
CallbackT& operator*() { return *ptr_; }
CallbackT* operator->() { return ptr_; }
CallbackT* get() const { return ptr_; };
CallbackT* release() {
if (ptr_) {
CallbackT* temp = ptr_;
ptr_ = nullptr;
return temp;
}
return ptr_;
}
private:
CallbackT* ptr_;
};
} // namespace mcj
namespace mcj {
template <typename CallbackT, typename ClosureT>
inline mcj::unique_ptr<CallbackT> make_unique(ClosureT&& closure) {
return mcj::unique_ptr<CallbackT>(new CallbackT(std::forward<ClosureT>(closure)));
}
然后我像这样测试我的 unique_ptr 并成功!
class A {
public:
A() {}
A(A* ptr) {
this->a = ptr->a;
this->b = ptr->b;
}
A(const A& ptr) {
this->a = ptr.a;
this->b = ptr.b;
}
A(A&& ptr) {
a = ptr.a;
b = ptr.b;
}
void GetA() { std::cout << "a:" << a << std::endl; }
int a = 0;
};
auto s1 = std::make_unique<A>();
s1->GetA();
mcj::unique_ptr<A> a(new A());
a->GetA();
mcj::unique_ptr<A> b(std::move(a));
b->GetA();
mcj::unique_ptr<A> c;
c = std::move(b);
c->GetA();
上面的例子表明我的 unique_ptr 已经成功覆盖了 operator->!而当我想尝试更复杂的 class 时,它失败了!请看下面的代码
namespace mcj {
class AppleCallback {
public:
virtual ~AppleCallback() = default;
virtual void OnAppleComplete(int err) = 0;
};
namespace callback_impl {
template <typename CallbackT, typename ClosureT>
class ClosureCallback : public CallbackT {
public:
explicit ClosureCallback(ClosureT&& closure)
: closure_(std::forward<ClosureT>(closure)) {}
protected:
typename std::remove_reference<ClosureT>::type closure_;
};
template <typename ClosureT>
class AppleCallbackImpl : public ClosureCallback<mcj::AppleCallback, ClosureT> {
public:
explicit AppleCallbackImpl(ClosureT&& closure)
: ClosureCallback<AppleCallback, ClosureT>(
std::forward<ClosureT>(closure)) {}
void OnAppleComplete(int err) override {
this->closure_(err);
}
};
} // namespace callback_impl
} // namespace mcj
namespace mcj {
template <typename CallbackT,
typename ClosureT,
typename std::enable_if<
std::is_same<CallbackT, AppleCallback>::value>::type* = nullptr>
mcj::unique_ptr<CallbackT> ToUniqueCallback(ClosureT&& closure) {
return mcj::make_unique<callback_impl::AppleCallbackImpl<ClosureT>>(
std::forward<ClosureT>(closure));
}
} // namespace mcj
namespace mcj {
template <typename CallbackT>
class MoveOnlyCallback {
using MyType = MoveOnlyCallback<CallbackT>;
mcj::unique_ptr<CallbackT> callback_;
public:
template <typename ClosureT>
MoveOnlyCallback(ClosureT&& closure)
: callback_(
ToUniqueCallback<CallbackT>(std::forward<ClosureT>(closure))) {
std::cout << "move constructor\n" << std::endl;
}
MoveOnlyCallback(std::unique_ptr<CallbackT> callback)
: callback_(std::move(callback)) {}
MoveOnlyCallback() = default;
MoveOnlyCallback(const MyType&) = delete;
MoveOnlyCallback(MyType&&) noexcept = default;
MyType& operator=(const MyType&) = delete;
MyType& operator=(MyType&&) noexcept = default;
CallbackT* operator->() const { return callback_.get(); }
explicit operator bool() const noexcept { return callback_.operator bool(); }
CallbackT* Get() const noexcept { return callback_.get(); };
CallbackT* Release() noexcept { return callback_.release(); }
mcj::unique_ptr<CallbackT> ReleaseUnique() noexcept {
return std::move(callback_);
}
};
class Apple : public Fruit {
public:
virtual ~Apple() = default;
void Name() override { std::cout << "I am apple \n" << std::endl; }
void Eat(MoveOnlyCallback<AppleCallback> callback) {
callback->OnAppleComplete(0);
// InvokeCallback(callback.Get(), 0);
}
};
} // namespace mcj
当我像这样调用 class“Apple”的函数“Eat”时,它会发生关于我的 unique_ptr 的操作-> 的错误,如果我替换我的 unique_ptr by std::unique_ptr, 没问题!
Apple* apple = new Apple();
apple->Eat(ToUniqueCallback<AppleCallback>(
[](int err) { std::cout << "eat callback" << std::endl; }));
这里是错误信息!
/Users/chaojie.mo/Documents/test/src/callback_utils.h:138:5: error:
type 'mcj::unique_ptrmcj::AppleCallback' does not provide a call
operator
this->closure_(err);
^~~~~~~~~~~~~~ /Users/chaojie.mo/Documents/test/src/callback_utils.h:134:12: note: in
instantiation of member function
'mcj::callback_impl::AppleCallbackImplmcj::unique_ptr<mcj::AppleCallback>::OnAppleComplete'
requested here explicit AppleCallbackImpl(ClosureT&& closure)
^ /Users/chaojie.mo/Documents/test/src/callback_utils.h:81:41: note: in
instantiation of member function
'mcj::callback_impl::AppleCallbackImplmcj::unique_ptr<mcj::AppleCallback>::AppleCallbackImpl'
requested here return mcj::unique_ptr(new
CallbackT(std::forward(closure)));
^ /Users/chaojie.mo/Documents/test/src/callback_utils.h:153:15: note: in
instantiation of function template specialization
'mcj::make_uniquemcj::callback_impl::AppleCallbackImpl<mcj::unique_ptr<mcj::AppleCallback>,
mcj::unique_ptrmcj::AppleCallback>' requested here return
mcj::make_unique<callback_impl::AppleCallbackImpl>(
^ /Users/chaojie.mo/Documents/test/src/callback_utils.h:168:13: note: in
instantiation of function template specialization
'mcj::ToUniqueCallback<mcj::AppleCallback,
mcj::unique_ptrmcj::AppleCallback, nullptr>' requested here
ToUniqueCallback(std::forward(closure))) {
^ /Users/chaojie.mo/Documents/test/test/main.cpp:77:14: note: in instantiation of function template specialization
'mcj::MoveOnlyCallbackmcj::AppleCallback::MoveOnlyCallbackmcj::unique_ptr<mcj::AppleCallback>'
requested here apple->Eat(ToUniqueCallback(
MoveOnlyCallback
有一个构造函数采用 std::unique_ptr
,但没有一个采用 mcj::unique_ptr
。从后者构建最终在通用构造函数 template <typename ClosureT> MoveOnlyCallback(ClosureT&& closure)
中。结果你得到了双重间接寻址,msj::unique_ptr<msj::unique_ptr<CallbackT>>
首先我自己实现unique_ptr:
namespace mcj {
template <typename CallbackT>
class unique_ptr {
public:
unique_ptr(CallbackT* ptr = nullptr) : ptr_(ptr) {}
template <
typename CallbackT1,
typename = typename std::enable_if<
std::is_convertible<CallbackT1*, CallbackT*>::value>::type>
unique_ptr(unique_ptr<CallbackT1>&& ptr) {
ptr_ = ptr.release();
}
unique_ptr(unique_ptr<CallbackT>&& ptr) {
if (ptr_) {
delete ptr_;
ptr_ = nullptr;
}
ptr_ = ptr.release();
}
template <
typename CallbackT1,
typename = typename std::enable_if<
std::is_convertible<CallbackT1*, CallbackT*>::value>::type>
unique_ptr<CallbackT>& operator=(unique_ptr<CallbackT1>&& ptr) {
ptr_ = ptr.release();
}
unique_ptr<CallbackT>& operator=(unique_ptr<CallbackT>&& ptr) {
if (ptr_) {
delete ptr_;
ptr_ = nullptr;
}
ptr_ = ptr.release();
return *this;
}
unique_ptr(const unique_ptr<CallbackT>& other) = delete;
unique_ptr<CallbackT>& operator=(const unique_ptr<CallbackT>& other) = delete;
~unique_ptr() {
delete ptr_;
ptr_ = nullptr;
}
CallbackT& operator*() { return *ptr_; }
CallbackT* operator->() { return ptr_; }
CallbackT* get() const { return ptr_; };
CallbackT* release() {
if (ptr_) {
CallbackT* temp = ptr_;
ptr_ = nullptr;
return temp;
}
return ptr_;
}
private:
CallbackT* ptr_;
};
} // namespace mcj
namespace mcj {
template <typename CallbackT, typename ClosureT>
inline mcj::unique_ptr<CallbackT> make_unique(ClosureT&& closure) {
return mcj::unique_ptr<CallbackT>(new CallbackT(std::forward<ClosureT>(closure)));
}
然后我像这样测试我的 unique_ptr 并成功!
class A {
public:
A() {}
A(A* ptr) {
this->a = ptr->a;
this->b = ptr->b;
}
A(const A& ptr) {
this->a = ptr.a;
this->b = ptr.b;
}
A(A&& ptr) {
a = ptr.a;
b = ptr.b;
}
void GetA() { std::cout << "a:" << a << std::endl; }
int a = 0;
};
auto s1 = std::make_unique<A>();
s1->GetA();
mcj::unique_ptr<A> a(new A());
a->GetA();
mcj::unique_ptr<A> b(std::move(a));
b->GetA();
mcj::unique_ptr<A> c;
c = std::move(b);
c->GetA();
上面的例子表明我的 unique_ptr 已经成功覆盖了 operator->!而当我想尝试更复杂的 class 时,它失败了!请看下面的代码
namespace mcj {
class AppleCallback {
public:
virtual ~AppleCallback() = default;
virtual void OnAppleComplete(int err) = 0;
};
namespace callback_impl {
template <typename CallbackT, typename ClosureT>
class ClosureCallback : public CallbackT {
public:
explicit ClosureCallback(ClosureT&& closure)
: closure_(std::forward<ClosureT>(closure)) {}
protected:
typename std::remove_reference<ClosureT>::type closure_;
};
template <typename ClosureT>
class AppleCallbackImpl : public ClosureCallback<mcj::AppleCallback, ClosureT> {
public:
explicit AppleCallbackImpl(ClosureT&& closure)
: ClosureCallback<AppleCallback, ClosureT>(
std::forward<ClosureT>(closure)) {}
void OnAppleComplete(int err) override {
this->closure_(err);
}
};
} // namespace callback_impl
} // namespace mcj
namespace mcj {
template <typename CallbackT,
typename ClosureT,
typename std::enable_if<
std::is_same<CallbackT, AppleCallback>::value>::type* = nullptr>
mcj::unique_ptr<CallbackT> ToUniqueCallback(ClosureT&& closure) {
return mcj::make_unique<callback_impl::AppleCallbackImpl<ClosureT>>(
std::forward<ClosureT>(closure));
}
} // namespace mcj
namespace mcj {
template <typename CallbackT>
class MoveOnlyCallback {
using MyType = MoveOnlyCallback<CallbackT>;
mcj::unique_ptr<CallbackT> callback_;
public:
template <typename ClosureT>
MoveOnlyCallback(ClosureT&& closure)
: callback_(
ToUniqueCallback<CallbackT>(std::forward<ClosureT>(closure))) {
std::cout << "move constructor\n" << std::endl;
}
MoveOnlyCallback(std::unique_ptr<CallbackT> callback)
: callback_(std::move(callback)) {}
MoveOnlyCallback() = default;
MoveOnlyCallback(const MyType&) = delete;
MoveOnlyCallback(MyType&&) noexcept = default;
MyType& operator=(const MyType&) = delete;
MyType& operator=(MyType&&) noexcept = default;
CallbackT* operator->() const { return callback_.get(); }
explicit operator bool() const noexcept { return callback_.operator bool(); }
CallbackT* Get() const noexcept { return callback_.get(); };
CallbackT* Release() noexcept { return callback_.release(); }
mcj::unique_ptr<CallbackT> ReleaseUnique() noexcept {
return std::move(callback_);
}
};
class Apple : public Fruit {
public:
virtual ~Apple() = default;
void Name() override { std::cout << "I am apple \n" << std::endl; }
void Eat(MoveOnlyCallback<AppleCallback> callback) {
callback->OnAppleComplete(0);
// InvokeCallback(callback.Get(), 0);
}
};
} // namespace mcj
当我像这样调用 class“Apple”的函数“Eat”时,它会发生关于我的 unique_ptr 的操作-> 的错误,如果我替换我的 unique_ptr by std::unique_ptr, 没问题!
Apple* apple = new Apple();
apple->Eat(ToUniqueCallback<AppleCallback>(
[](int err) { std::cout << "eat callback" << std::endl; }));
这里是错误信息!
/Users/chaojie.mo/Documents/test/src/callback_utils.h:138:5: error: type 'mcj::unique_ptrmcj::AppleCallback' does not provide a call operator this->closure_(err); ^~~~~~~~~~~~~~ /Users/chaojie.mo/Documents/test/src/callback_utils.h:134:12: note: in instantiation of member function 'mcj::callback_impl::AppleCallbackImplmcj::unique_ptr<mcj::AppleCallback>::OnAppleComplete' requested here explicit AppleCallbackImpl(ClosureT&& closure) ^ /Users/chaojie.mo/Documents/test/src/callback_utils.h:81:41: note: in instantiation of member function 'mcj::callback_impl::AppleCallbackImplmcj::unique_ptr<mcj::AppleCallback>::AppleCallbackImpl' requested here return mcj::unique_ptr(new CallbackT(std::forward(closure))); ^ /Users/chaojie.mo/Documents/test/src/callback_utils.h:153:15: note: in instantiation of function template specialization 'mcj::make_uniquemcj::callback_impl::AppleCallbackImpl<mcj::unique_ptr<mcj::AppleCallback>, mcj::unique_ptrmcj::AppleCallback>' requested here return mcj::make_unique<callback_impl::AppleCallbackImpl>( ^ /Users/chaojie.mo/Documents/test/src/callback_utils.h:168:13: note: in instantiation of function template specialization 'mcj::ToUniqueCallback<mcj::AppleCallback, mcj::unique_ptrmcj::AppleCallback, nullptr>' requested here ToUniqueCallback(std::forward(closure))) { ^ /Users/chaojie.mo/Documents/test/test/main.cpp:77:14: note: in instantiation of function template specialization 'mcj::MoveOnlyCallbackmcj::AppleCallback::MoveOnlyCallbackmcj::unique_ptr<mcj::AppleCallback>' requested here apple->Eat(ToUniqueCallback(
MoveOnlyCallback
有一个构造函数采用 std::unique_ptr
,但没有一个采用 mcj::unique_ptr
。从后者构建最终在通用构造函数 template <typename ClosureT> MoveOnlyCallback(ClosureT&& closure)
中。结果你得到了双重间接寻址,msj::unique_ptr<msj::unique_ptr<CallbackT>>