c++smart-pointersmingw-w64ownership-semantics

Build error of "No matching constructor for initialization" when initialize share_ptr<T[]> from unique_ptr<T[]>


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:


Solution

  • If I use llvm-mingw v18.1.8 rather than v12.0.0, then it works.