C++ Arrays and make_unique
Asked Answered
H

2

13

As a follow up to this post I wonder how its implementation of make_unique plays with allocating function-temporary buffer arrays such as in the following code.

f()
{
  auto buf = new int[n]; // temporary buffer
  // use buf ...
  delete [] buf;
}

Can this be replaced with some call to make_unique and will the []-version of delete be used then?

Hypercatalectic answered 14/4, 2012 at 0:7 Comment(1)
Reading the answers: no, there is no simple answer :(Titos
T
19

Here is another solution (in addition to Mike's):

#include <type_traits>
#include <utility>
#include <memory>

template <class T, class ...Args>
typename std::enable_if
<
    !std::is_array<T>::value,
    std::unique_ptr<T>
>::type
make_unique(Args&& ...args)
{
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

template <class T>
typename std::enable_if
<
    std::is_array<T>::value,
    std::unique_ptr<T>
>::type
make_unique(std::size_t n)
{
    typedef typename std::remove_extent<T>::type RT;
    return std::unique_ptr<T>(new RT[n]);
}

int main()
{
    auto p1 = make_unique<int>(3);
    auto p2 = make_unique<int[]>(3);
}

Notes:

  1. new T[n] should just default construct n T's.

So make_unique(n) should just default construct n T's.

  1. Issues like this contributed to make_unique not being proposed in C++11. Another issue is: Do we handle custom deleters?

These are not unanswerable questions. But they are questions that haven't yet been fully answered.

Triny answered 14/4, 2012 at 1:14 Comment(2)
... but these questions have been (partially) answered in C++14, and make_unique is now richer.Evaginate
@einpoklum: Correct. Note the date on the Q/A.Triny
C
4

I got it working with this code:

#include <memory>
#include <utility>

namespace Aux {
    template<typename Ty>
    struct MakeUnique {
        template<typename ...Args>
        static std::unique_ptr<Ty> make(Args &&...args) {
            return std::unique_ptr<Ty>(new Ty(std::forward<Args>(args)...));
        }
    };

    template<typename Ty>
    struct MakeUnique<Ty []> {
        template<typename ...Args>
        static std::unique_ptr<Ty []> make(Args &&...args) {
            return std::unique_ptr<Ty []>(new Ty[sizeof...(args)]{std::forward<Args>(args)...});
        }
    };
}

template<typename Ty, typename ...Args>
std::unique_ptr<Ty> makeUnique(Args &&...args) {
    return Aux::MakeUnique<Ty>::make(std::forward<Args>(args)...);
}
Culinary answered 14/4, 2012 at 1:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.