2012-11-16 25 views
0

我想要的东西就像unique_ptr,但保证(在合理范围内)是非空的。我写了这个包含unique_ptr的类,并且我写了这个移动构造函数,我希望这个移动构造函数可以让我移动 - 构建我的另一个指针,只要底层的unique_ptr可以类似移动构建。所以,我先用简单的东西来尝试一下吧。移动 - 从指针到int的构造指针到int。模板化移动ctor以包装unique_ptr

#include <memory> 
#include <utility> 
#include <cassert> 


template< 
    typename T 
    > 
class Nonup 
{ 
    private: 

     std::unique_ptr<T> m_ptr; 

    public: 

     explicit Nonup(T* p) 
     : m_ptr(p) 
     { assert(p); } 

     Nonup(const Nonup&) = delete; 
     Nonup& operator=(const Nonup&) = delete; 

     template<typename U> 
     Nonup(Nonup<U>&& old) 
     : 
      m_ptr(std::move(old)) 
     {} 

     Nonup& operator=(Nonup&& rhs) = default; 

     decltype(*m_ptr) operator*() const { return *m_ptr; } 
}; 


int main() 
{ 
    Nonup<int> first(new int(42)); 

    Nonup<int> second(std::move(first)); 

    return 0; 
} 

为什么g ++ 4.7.0在移动构造变量second时出错?接下来是“g ++ -std = C++ 11 main.cpp”的输出。

main.cpp: In instantiation of ‘Nonup<T>::Nonup(Nonup<U>&&) [with U = int; T = int]’: 
main.cpp:40:43: required from here 
main.cpp:27:37: error: no matching function for call to ‘std::unique_ptr<int, std::default_delete<int> >::unique_ptr(std::remove_reference<Nonup<int>&>::type)’ 
main.cpp:27:37: note: candidates are: 
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/memory:86:0, 
       from main.cpp:1: 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:164:2: note: template<class _Up, class> std::unique_ptr::unique_ptr(std::auto_ptr<_Up>&&) 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:164:2: note: template argument deduction/substitution failed: 
main.cpp:27:37: note: ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ is not derived from ‘std::auto_ptr<_Up>’ 
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/memory:86:0, 
       from main.cpp:1: 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:155:2: note: template<class _Up, class _Ep, class> std::unique_ptr::unique_ptr(std::unique_ptr<_Up, _Ep>&&) 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:155:2: note: template argument deduction/substitution failed: 
main.cpp:27:37: note: ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ is not derived from ‘std::unique_ptr<_Up, _Ep>’ 
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/memory:86:0, 
       from main.cpp:1: 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:142:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>&&) [with _Tp = int; _Dp = std::default_delete<int>] 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:142:7: note: no known conversion for argument 1 from ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ to ‘std::unique_ptr<int, std::default_delete<int> >&&’ 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:136:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr(std::nullptr_t) [with _Tp = int; _Dp = std::default_delete<int>; std::nullptr_t = std::nullptr_t] 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:136:17: note: no known conversion for argument 1 from ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ to ‘std::nullptr_t’ 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:130:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::remove_reference<_To>::type&&) [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp>::pointer = int*; typename std::remove_reference<_To>::type = std::default_delete<int>] 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:130:7: note: candidate expects 2 arguments, 1 provided 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:125:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer, typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type) [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp>::pointer = int*; typename std::conditional<std::is_reference<_Dp>::value, _Dp, const _Dp&>::type = const std::default_delete<int>&] 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:125:7: note: candidate expects 2 arguments, 1 provided 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:120:7: note: std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = int; _Dp = std::default_delete<int>; std::unique_ptr<_Tp, _Dp>::pointer = int*] 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:120:7: note: no known conversion for argument 1 from ‘std::remove_reference<Nonup<int>&>::type {aka Nonup<int>}’ to ‘std::unique_ptr<int, std::default_delete<int> >::pointer {aka int*}’ 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:114:17: note: constexpr std::unique_ptr<_Tp, _Dp>::unique_ptr() [with _Tp = int; _Dp = std::default_delete<int>] 
/usr/lib/gcc/x86_64-redhat-linux/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:114:17: note: candidate expects 0 arguments, 1 provided 

谢谢!

+2

你怎么能指望支持单所有权转移语义*和*保证它的非空(并指向一个有效的对象)?如果新的所有者不使旧所有者无效,那么旧所有者的指针可能会悬空。 –

+0

我也有“指向有效对象”的担忧,但可能只有我能做的很多;同样,我们也不能保证引用总是有效的,尽管它在声明时一定是有效的。 – user1588202

+0

至于无效的老主人,在我看来,不应该尝试使用已经是std :: move()的主题。也许我误解(或者高估)了这个函数的含义。 – user1588202

回答

1

您正试图从Nonup而不是其m_ptr初始化m_ptr。此举构造函数初始化器应该是:

m_ptr(std::move(old.m_ptr)) 
        ^^^^^^ 
+0

啊,当然。非常感谢你! – user1588202