0

Why can't i initialize a unique pointer

#include <iostream>
#include <memory>

class Widget
{
    std::unique_ptr<int[]> arr;
    
public:
    Widget(int size)
    {
        arr = std::make_unique<int[size]>();
    }
    ~Widget()
    {
        
    }
};

int main()
{
    
}

I am not able to understand the meaning of below error messages. What is wrong with my invocation of arr = std::make_unique<int[size]>();

I am just trying to create a class with unique pointer member which manages an array. How should I change the below program and WHY?

Error(s):
1129699974/source.cpp: In constructor ‘Widget::Widget(int)’:
1129699974/source.cpp:13:43: error: no matching function for call to ‘make_unique<int [size]>()’
         arr = std::make_unique<int[size]>();
                                           ^
In file included from /usr/include/c++/7/memory:80:0,
                 from 1129699974/source.cpp:4:
/usr/include/c++/7/bits/unique_ptr.h:824:5: note: candidate: template<class _Tp, class ... _Args> typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...)
     make_unique(_Args&&... __args)
     ^~~~~~~~~~~
/usr/include/c++/7/bits/unique_ptr.h:824:5: note:   template argument deduction/substitution failed:
/usr/include/c++/7/bits/unique_ptr.h: In substitution of ‘template<class _Tp, class ... _Args> typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = int [size]; _Args = {}]’:
1129699974/source.cpp:13:43:   required from here
/usr/include/c++/7/bits/unique_ptr.h:824:5: error: ‘int [size]’ is a variably modified type
/usr/include/c++/7/bits/unique_ptr.h:824:5: error:   trying to instantiate ‘template<class _Tp> struct std::_MakeUniq’
/usr/include/c++/7/bits/unique_ptr.h:830:5: note: candidate: template<class _Tp> typename std::_MakeUniq<_Tp>::__array std::make_unique(std::size_t)
     make_unique(size_t __num)
     ^~~~~~~~~~~
/usr/include/c++/7/bits/unique_ptr.h:830:5: note:   template argument deduction/substitution failed:
/usr/include/c++/7/bits/unique_ptr.h: In substitution of ‘template<class _Tp> typename std::_MakeUniq<_Tp>::__array std::make_unique(std::size_t) [with _Tp = int [size]]’:
1129699974/source.cpp:13:43:   required from here
/usr/include/c++/7/bits/unique_ptr.h:830:5: error: ‘int [size]’ is a variably modified type
/usr/include/c++/7/bits/unique_ptr.h:830:5: error:   trying to instantiate ‘template<class _Tp> struct std::_MakeUniq’
/usr/include/c++/7/bits/unique_ptr.h:836:5: note: candidate: template<class _Tp, class ... _Args> typename std::_MakeUniq<_Tp>::__invalid_type std::make_unique(_Args&& ...) <deleted>
     make_unique(_Args&&...) = delete;
     ^~~~~~~~~~~
/usr/include/c++/7/bits/unique_ptr.h:836:5: note:   template argument deduction/substitution failed:
/usr/include/c++/7/bits/unique_ptr.h: In substitution of ‘template<class _Tp, class ... _Args> typename std::_MakeUniq<_Tp>::__invalid_type std::make_unique(_Args&& ...) [with _Tp = int [size]; _Args = {}]’:
1129699974/source.cpp:13:43:   required from here
/usr/include/c++/7/bits/unique_ptr.h:836:5: error: ‘int [size]’ is a variably modified type
/usr/include/c++/7/bits/unique_ptr.h:836:5: error:   trying to instantiate ‘template<class _Tp> struct std::_MakeUniq’
2
  • 2
    The error in the use case is explained in the answer, but just a note in general: size doesn't have a compile-time constant value. A template argument, such as int[size] in std::make_unique<int[size]> can never depend on a value that is not a compile-time constant. Commented Feb 20, 2022 at 4:00
  • @user17732522 : thanks. The error makes much more sense now. But it's bit different when we initialize a pointer to array of ints and hence I wrote code incorrectly Commented Feb 20, 2022 at 4:06

1 Answer 1

3

You need

arr = std::make_unique<int[]>(size);

make_unique has a specific documented usage:

template< class T > unique_ptr<T> make_unique( std::size_t size );`

... Constructs an array of the given dynamic size. The array elements are value-initialized. This overload participates in overload resolution only if T is an array of unknown bound. The function is equivalent to:

unique_ptr<T>(new std::remove_extent_t<T>[size]())

Conceptually-speaking1, you can think of make_unique as being very similar to std::unique_ptr<T>(new T(...)) where ... represents forwarding of the args passed to make_unique. In this case, the usage is analogous to forwarding the one arg to operator new[] (std::size_t size)

1 The documentation I linked above doesn't say that the arg is forwarded in the array case, and I don't believe the spec does either.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.