質問: N4189で提案されているUnique Resourceが便利そうなので、簡易版を自ソフトへ取り込もうとしています。 この資料の16ページ 8.2 Unique Resourceに実装例が記載されているのですが、何か変です。 #### 疑問1 ``` template class unique_resource{ R resource; D deleter; bool execute_on_destruction; // exposition only (中略) // construction explicit unique_resource(R && resource, D && deleter, bool shouldrun=true) noexcept : resource(std::move(resource)) , deleter(std::move(deleter)) , execute_on_destruction{shouldrun}{} (中略) //factories template auto make_unique_resource( R && r,D &&d) noexcept { return unique_resource>( std::move(r) ,std::forward>(d) ,true); } ``` となっているのですが、std::move()しているためresourceに参照を渡せないように思います。 **実験** 普通に名前付きインスタンス(std::vector foo;のfoo)をfactoryに渡したところ、msvc 2015ではstd::move()のままでも通ったのですが、MinGW 5.2.0ではエラーになりました。 ``` error: invalid initialization of non-const reference of type 'std::vector&' from an rvalue of type 'std::remove_reference&>::type {aka std::vector}' ``` そして、std::forward<>へ変更することでビルドと実行できるようになりました。 これは実装例のミスと考えて間違いないでしょうか? 私自身のstd::forwardの理解が浅いのでいまいち確信が持てないのです。 #### 疑問2 次に、factoryでremove_referenceされていますが、この必要性が分かりません。 **実験** remove_reference_tが2箇所にあります。このままでも動作するのですが、両方ともremove_reference_t<>をやめて、ラムダ式を与えてみたところ問題なく動作しました。 このremove_reference_t<>は不要と考えて間違いないでしょうか? 意味もなくコードが複雑になるのは好ましくないので、不要なら削除しようと思います。
回答: Unique Resourceは文字通り「Uniqueな/他と共有しない排他的な」資源を扱うため、参照を渡せないのは設計通りかと思います。 > > 普通に名前付きインスタンス(std::vector foo;のfoo)をfactoryに渡したところ、msvc 2015ではstd::move()のままでも通ったのですが、MinGW 5.2.0ではエラーになりました。 > > > MinGW 5.2.0の挙動が正しいはずです。オブジェクトは変数`foo`で既に管理されているため、そこからUnique Resourceを作ってはいけません/禁止されるべきです。 > > 次に、factoryでremove_referenceされていますが、この必要性が分かりません。 > > > `make_unique_resource`第二引数に左辺値を渡すケースで必要になると思います。 * 1個目:このケースではテンプレートパラメータ`D`は左辺値参照`T&`に推論されるため、`unique_resource::deleter`を非左辺値参照とするための`remove_reference_t`だと思います。 * 2個目:`std::forward>(d)`は`std::move(d)`と等価なような... Give Up.