Should I use() or {} when forwarding arguments?を参照してください。 foo
はクローンstd::vector
です。 N4140、unique.ptr.createstd::make_unique
でstd :: make_unique et alのstd :: initializer_listオーバーロードがなぜ存在しないのですか?
になるように指定されている:
template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
は備考:
T
が配列でない場合を除き、この機能は、オーバーロード解決に参加してはなりません。:
unique_ptr<T>(new T(std::forward<Args>(args)...))
を返します。実装を意味
は、オブジェクトを初期化するために()
なく{}
を使用する必要があります。一例として、
auto s1 = std::make_unique<foo>(3, 1).get()->size();
auto s2 = std::make_unique<foo>(1).get()->size();
auto s3 = std::make_unique<foo>(2).get()->size();
std::cout << s1 << s2 << s3;
出力312
{}
(std::make_unique
内側)を使用した場合には211
なり、一方の出力を以下。初期化子リストを推測できないため、後者の結果を得るには、std::initializer_list
を明示的に渡す必要があります。問題は、なぜこのような過負荷は提供されていないのでしょうか?
namespace test
{
template <class T, class Deduce>
std::unique_ptr<T> make_unique(std::initializer_list<Deduce> li)
{
return ::std::make_unique<T>(li);
}
};
int main()
{
auto p1 = test::make_unique<foo>({3, 1}).get()->size();
auto p2 = test::make_unique<foo>({1}).get()->size();
auto p3 = test::make_unique<foo>({2}).get()->size();
std::cout << p1 << p2 << p3;
}
出力211
。
"自分で書くことができる"または "標準を膨らませない"という理由は非常に良い理由とは考えられません。この過負荷を提供することに不利な点はありますか?
私はSFINAEが必要だとは思いません。 'make_unique>(1,73);'ネームスペースから取り出して 'using namespace std;'を実行すると、両方のオーバーロードが見えるようになります。誰かが 'make_unique >({1,73});'それは彼らのせいです。 –
user6319825
@ user6319825。はい、SFINAEは必須ではなく、どちらの方法でもコンパイルに失敗します。私の経験では、SFINAE環境のエラーメッセージは診断するのが簡単です。まだ – Niall
。彼らは[オプション](http://eel.is/c++draft/optional.object)のような実装に任せるのではなく、 '新しいT(std :: forward(args)...)'を考察しました。 .ctor#23): "' std :: forward (args) 'の引数を使って' T '型のオブジェクトを直接非非リスト初期化するかのように、格納された値を初期化します。いくつかの議論*どこかで*少なくともmake_uniqueのために。 –
user6319825