First, I read this answer to realize why we want to convert an unique_ptr
to a shared_ptr
sometimes. Then, I follow the instructions of the converting constructor on cppreference shared_ptr.
In C++11 and C++14 it is valid to construct a std::shared_ptr<T> from a std::unique_ptr<T[]>:
std::unique_ptr<int[]> arr(new int[1]);
std::shared_ptr<int> ptr(std::move(arr));
Since the shared_ptr obtains its deleter (a std::default_delete<T[]> object) from the std::unique_ptr, the array will be correctly deallocated.
This is no longer allowed in C++17. Instead the array form std::shared_ptr<T[]> should be used.
So, I try it on Ubuntu and Windows, respectively. The following code can be built PASS on Ubuntu using g++ v11.4.0
g++ -std=c++17 ./test.cpp -o test_cpp
#include <memory>
int main()
{
std::unique_ptr<int[]> arr(new int[1]);
std::shared_ptr<int[]> ptr(std::move(arr));
return 0;
}
On the other hand, it shows the following error messages on Windows 11 using llvm-mingw g++ v12.0.0, which can be downloaded from here:
.\test.cpp:6:28: error: no matching constructor for initialization of 'std::shared_ptr<int []>'
std::shared_ptr<int[]> ptr(std::move(arr));
^ ~~~~~~~~~~~~~~
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2711:23: note: candidate constructor not viable: no known conversion from 'typename remove_reference<unique_ptr<int []> &>::type'
(aka 'std::unique_ptr<int []>') to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument
_LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT;
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2725:5: note: candidate constructor not viable: no known conversion from 'typename remove_reference<unique_ptr<int []> &>::type'
(aka 'std::unique_ptr<int []>') to 'const std::shared_ptr<int []>' for 1st argument
shared_ptr(const shared_ptr& __r) _NOEXCEPT;
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2732:5: note: candidate constructor not viable: no known conversion from 'typename remove_reference<unique_ptr<int []> &>::type'
(aka 'std::unique_ptr<int []>') to 'std::shared_ptr<int []>' for 1st argument
shared_ptr(shared_ptr&& __r) _NOEXCEPT;
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2713:18: note: candidate template ignored: could not match '_Yp *' against 'typename remove_reference<unique_ptr<int []> &>::type'
(aka 'std::unique_ptr<int []>')
explicit shared_ptr(_Yp* __p,
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2728:9: note: candidate template ignored: could not match 'shared_ptr' against 'unique_ptr'
shared_ptr(const shared_ptr<_Yp>& __r,
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2733:52: note: candidate template ignored: could not match 'shared_ptr' against 'unique_ptr'
template<class _Yp> _LIBCPP_INLINE_VISIBILITY shared_ptr(shared_ptr<_Yp>&& __r,
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2736:34: note: candidate template ignored: could not match 'weak_ptr' against 'unique_ptr'
template<class _Yp> explicit shared_ptr(const weak_ptr<_Yp>& __r,
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2744:9: note: candidate template ignored: requirement '!is_array<int []>::value' was not satisfied
[with _Yp = int [], _Dp = std::default_delete<int []>]
shared_ptr(unique_ptr<_Yp, _Dp>&&,
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2753:9: note: candidate template ignored: requirement 'is_lvalue_reference<std::default_delete<int []>>::value' was not satisfied
[with _Yp = int [], _Dp = std::default_delete<int []>]
shared_ptr(unique_ptr<_Yp, _Dp>&&,
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2709:23: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
_LIBCPP_CONSTEXPR shared_ptr() _NOEXCEPT;
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2721:26: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
template <class _Dp> shared_ptr(nullptr_t __p, _Dp __d);
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2723:51: note: candidate constructor template not viable: requires 2 arguments, but 1 was provided
template<class _Yp> _LIBCPP_INLINE_VISIBILITY shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) _NOEXCEPT;
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2716:9: note: candidate constructor template not viable: requires at least 2 arguments, but 1 was provided
shared_ptr(_Yp* __p, _Dp __d,
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2722:40: note: candidate constructor template not viable: requires 3 arguments, but 1 was provided
template <class _Dp, class _Alloc> shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a);
^
C:\local\llvm-mingw-20210423-msvcrt-x86_64\include\c++\v1\memory:2719:9: note: candidate constructor template not viable: requires at least 3 arguments, but 1 was provided
shared_ptr(_Yp* __p, _Dp __d, _Alloc __a,
^
1 error generated.
If I change the allocated resource from array of objects to object, then it works.
std::unique_ptr<int> arr(new int{1});
std::shared_ptr<int> ptr(std::move(arr));
So, my question is:
If I use llvm-mingw v18.1.8 rather than v12.0.0, then it works.