標準C++ 11ライブラリにstd::make_unique
関数テンプレートがないのはなぜですか?見つける
std::unique_ptr<SomeUserDefinedType> p(new SomeUserDefinedType(1, 2, 3));
少し冗長です。次の方がはるかに優れていませんか?
auto p = std::make_unique<SomeUserDefinedType>(1, 2, 3);
これにより、new
が適切に非表示になり、タイプについて1回だけ言及されます。
とにかく、ここにmake_unique
の実装の試みがあります:
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
std::forward
をコンパイルするにはかなり時間がかかりましたが、それが正しいかどうかはわかりません。それは...ですか? std::forward<Args>(args)...
はどういう意味ですか?コンパイラはそれで何を作りますか?
いいですが、Stephan T. Lavavej(よりよくSTLとして知られています)には、make_unique
のより良い解決策があります。これは、配列バージョンに対して正しく動作します。
#include <memory>
#include <type_traits>
#include <utility>
template <typename T, typename... Args>
std::unique_ptr<T> make_unique_helper(std::false_type, Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
template <typename T, typename... Args>
std::unique_ptr<T> make_unique_helper(std::true_type, Args&&... args) {
static_assert(std::extent<T>::value == 0,
"make_unique<T[N]>() is forbidden, please use make_unique<T[]>().");
typedef typename std::remove_extent<T>::type U;
return std::unique_ptr<T>(new U[sizeof...(Args)]{std::forward<Args>(args)...});
}
template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return make_unique_helper<T>(std::is_array<T>(), std::forward<Args>(args)...);
}
これは 彼のCore C++ 6ビデオ で見ることができます。
Make_uniqueのSTLバージョンの更新バージョンが N3656 として利用可能になりました。このバージョン 採用された ドラフトC++ 14に。
std::make_shared
はstd::shared_ptr<Type> ptr(new Type(...));
の省略形ではありません。それはあなたができませんなしでやることをします。
その仕事をするために、std::shared_ptr
は、実際のポインタ用のストレージを保持することに加えて、追跡ブロックを割り当てる必要があります。ただし、std::make_shared
は実際のオブジェクトを割り当てるため、std::make_shared
はオブジェクトの両方を割り当てますおよび同じメモリブロック内のトラッキングブロック。
したがって、std::shared_ptr<Type> ptr = new Type(...);
は2つのメモリ割り当て(1つはnew
用、1つはstd::shared_ptr
トラッキングブロック用)になりますが、std::make_shared<Type>(...)
はoneブロックを割り当てますメモリの。
これは、std::shared_ptr
の多くの潜在的なユーザーにとって重要です。 std::make_unique
が行う唯一のことは、もう少し便利です。それ以上のものはありません。
C++ 11では、...
も(テンプレートコードで) "パック拡張"に使用されます。
要件は、パラメータの展開されていないパックを含む式の接尾辞として使用することです。パックの各要素に式を単純に適用します。
たとえば、あなたの例に基づいて:
std::forward<Args>(args)... -> std::forward<int>(1), std::forward<int>(2),
std::forward<int>(3)
std::forward<Args...>(args...) -> std::forward<int, int, int>(1,2,3)
後者は間違っていると思います。
また、引数のパックは、展開されていない関数に渡されることはありません。テンプレートパラメータのパックについて確信が持てません。
Stephan T. Lavavejによる実装に触発されて、配列エクステントをサポートするmake_uniqueがあればいいのではないかと思いました githubにあります そして、それについてコメントをもらいたいです。これを行うことができます:
// create unique_ptr to an array of 100 integers
auto a = make_unique<int[100]>();
// create a unique_ptr to an array of 100 integers and
// set the first three elements to 1,2,3
auto b = make_unique<int[100]>(1,2,3);