2012-04-14 35 views
11

私はmake_uniqueの実装がどのように次のコードのような関数の一時バッファ配列を割り当てることで果たしているのだろうかというと、thisの投稿に続きます。C++の配列とmake_unique

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

このmake_uniqueにいくつかの呼び出しに置き換えることができ、削除の[] -versionは、その後に使用されるのですか?

答えて

16

は、(マイクのに加えて)別のソリューションです

  1. 新しいT [N] n Tをデフォルトで構築する必要があります。

したがって、make_unique(n)はデフォルトでnTを構成する必要があります。

  1. このような問題は、C++ 11で提案されていないmake_uniqueに寄与しています。別の問題は次のとおりです。カスタムの削除者を処理しますか?

これは疑問のない質問です。しかし、彼らはまだ完全に答えられていない質問です。

+0

...これらの質問はC++ 14で(部分的に)回答されており、make_uniqueは現在よりリッチです(http://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique)。 – einpoklum

+0

@einpoklum:正しい。 Q/Aの日付を書き留めます。 –

4

私はそれがこのコードで作業しました:

#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); 
} 

注:ここでは

#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)...); 
}