2016-05-11 6 views
5

Should I use() or {} when forwarding arguments?を参照してください。 fooはクローンstd::vectorです。 N4140、unique.ptr.createstd::make_uniquestd :: 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

"自分で書くことができる"または "標準を膨らませない"という理由は非常に良い理由とは考えられません。この過負荷を提供することに不利な点はありますか?

答えて

2

完全な履歴はわかりませんが、最も可能性の高い回答は「誰も提案していません」です。

std::make_uniqueはC++ 14でのみ追加されていますが、std::unique_ptrはC++ 11に追加されています。

(最終的make_uniqueに反映した)std::make_sharedためのコードと提案が前initializer_listとそれを支持する初期化構文に(ブーストに)存在していました。

あなたが今できることの1つは、それを提案することです(ターゲットタイプがinitializer_listをサポートしていない場合は、SFINAEを使用してオーバーロードを削除するなど)。

+0

私はSFINAEが必要だとは思いません。 'make_unique >(1,73);'ネームスペースから取り出して 'using namespace std;'を実行すると、両方のオーバーロードが見えるようになります。誰かが 'make_unique >({1,73});'それは彼らのせいです。 – user6319825

+0

@ user6319825。はい、SFINAEは必須ではなく、どちらの方法でもコンパイルに失敗します。私の経験では、SFINAE環境のエラーメッセージは診断するのが簡単です。まだ – Niall

+0

。彼らは[オプション](http://eel.is/c++draft/optional.object)のような実装に任せるのではなく、 '新しいT(std :: forward (args)...)'を考察しました。 .ctor#23): "' std :: forward (args) 'の引数を使って' T '型のオブジェクトを直接非非リスト初期化するかのように、格納された値を初期化します。いくつかの議論*どこかで*少なくともmake_uniqueのために。 – user6319825

0

テンプレート控除の問題だと思うのですが、this answerを参照してください。

あなたはこれらを試みることができる:

int main() 
{ 
    auto p1 = std::make_unique<foo>(std::initializer_list<int>{3, 1}).get()->size(); 
    auto p2 = std::make_unique<foo>(foo{1}).get()->size(); 
    auto l3 = {2}; 
    auto p3 = std::make_unique<foo>(l3).get()->size(); 
    std::cout << p1 << p2 << p3; 
} 
関連する問題