問題タブ [perfect-forwarding]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票する
3 に答える
1058 参照

c++ - r値でstd::forwardを使用しない場合は?

不要な場合 std::forwardはどうなりますか?これは、templated-rvalueである内部関数引数をラップするために使用されます(つまり、lvalueまたはnamed-rvalueにすることができます)。のように:

1つのケースは、内部関数パラメーターが値によって渡される場合だと思います。他にケースはありますか?std::begin(std::forward<Ct>(ct))Ctがtemplated-rvalue-refである場所を書いているときに、この質問があります。

重複の可能性について編集

私の記憶が正しければ、これは、この4年前の質問を、質問を理解していない初心者が複製したものとして閉じる3回目の試みです。

「フォワードを使用する利点は?」および「r値でstd::forwardを使用しない場合は?」非常に異なる質問です。1つ目は、初心者向けのr値の紹介であり、2つ目は、上級C++ユーザー向けの完全な転送についての説明です。私はメタテンプレートライブラリとラムダライブラリの作成者であり、基本の詳細な説明は必要ありません。回答の情報は他の質問とは大きく異なります。

0 投票する
1 に答える
665 参照

c++ - (おそらく抽象)基本クラスの保護されたコンストラクターの検出

私はC++11の新機能を試しています。私のセットアップでは、継承コンストラクターを使用したいのですが、残念ながら、まだそれらを実装しているコンパイラーはありません。したがって、私は同じ動作をシミュレートしようとしています。私はこのようなものを書くことができます:

これは機能します...ほとんどの場合。クラスを使用するコードは、WrapperSFINAEを使用して、そのようなコードをWrapper<T>構築する方法を検出する必要がある場合があります。ただし、次の問題があります。オーバーロードの解決に関する限り、のコンストラクターはWrapper<T>すべての引数を受け入れますが、それらを使用して型を構築できない場合、コンパイルは失敗します(これはSFINAEではカバーされません)。T

コンストラクターテンプレートのさまざまなインスタンス化を条件付きで有効にしようとしていましたenable_if

次の場合に限り、正常に機能します。

  • の適切なコンストラクタTpublic
  • T抽象的ではありません

私の質問は、上記の2つの制約を取り除く方法です。

式が内で整形sizeof()式であるかどうかを(SFINAEとを使用して)チェックすることにより、最初の問題を克服しようとしました。ただし、これはもちろん機能しません。派生クラスがそのベースの保護されたコンストラクターを使用できる唯一の方法は、メンバーの初期化リストにあるためです。new T(std::declval<As &&>()...) Wrapper<T>

2つ目については、まったくわかりません。これは、Wrapperの抽象関数を実装しTて完全な型にすることがあるため、さらに必要なものです。

私は次のような解決策が必要です:

  • 標準に従って正しい
  • gcc-4.6。*、gcc-4.7。*、またはclang-3。*のいずれかで動作します

ありがとう!

0 投票する
3 に答える
188 参照

c++ - R値とL値で出力が異なります。なんで?

R値の出力がL値と異なる理由を誰かに説明してもらえますか?

出力 (gcc48 と clang32 で同じ):

答え

Johannes Schaub とのチャットで少し埋もれてしまったので、ここに記載します。

一時的なベクトルが r-value-ref member-variable を初期化する場合rv.ct、特別な例外があるため、一時的な有効期間は延長されません: [class.temporary]p5: "コンストラクターの ctor-initializer (12.6.2) で参照メンバーに一時的にバインドされています。コンストラクターが終了するまで持続します。」

0 投票する
3 に答える
6741 参照

c++ - 戻り値の転送。std::forward は必要ですか?

私は他のライブラリから多くの関数とメソッドをラップするライブラリを書いています。戻り値の対処を避けるために、私は次のstd::forwardように適用しています:

f返しvoidて取るT&&(または価値をオーバーロードする)。ラッパーは常にラッパーのパラメーターを返し、戻り値では引数の値を保持する必要があります。実際に使用する必要がありstd::forwardますreturnか? RVOはそれを不要にしますか?それが参照 (R または L) であるという事実は、それを不必要にしますか? return が最後の関数ステートメントではない場合 (if 内) は必要ですか?

呼び出し元は arg (参照、R または L) を介して評価された値にアクセスできるため、またはwrapper()を返す必要があるかどうかは議論の余地があります。しかし、私の場合、式で使用できるように値を返す必要があります。voidT&&wrapper()

質問とは無関係かもしれませんが、関数fは から盗まないことが知られているため、 intの最初の使用は不要であり、私によって削除されました。std::forwardf(std::forward<T>(t))

私は小さなテストを書きました: https://gist.github.com/3910503

テストでは、転送されずに返されることTが示されています - -O3 を使用して gcc48 と clang32 に追加のコピーを作成します (RVO は起動しません)。

また、次の UB から悪い動作を取得できませんでした。

未定義の動作であるため (UB の場合)、何の原因も証明されません。

0 投票する
3 に答える
1658 参照

c++ - クラス階層内の完全な転送コンストラクターとコピーコンストラクター間の競合

最近、完全な転送コンストラクターを使用してクラス階層を実装しようとしたときに問題が発生しました。次の例を考えてみましょう。

コードをコンパイルしようとすると、次のエラーが発生します。

エラー3エラーC2664:'std :: basic_string <_Elem、_Traits、_Alloc> :: basic_string(const std :: basic_string <_Elem、_Traits、_Alloc>&)':パラメータ1を'constTest'から'conststdに変換できません:: basic_string <_Elem、_Traits、_Alloc>& '

私の理解では、コンパイラーは完全な転送コンストラクターをコピーコンストラクターよりも優れた数学として扱います。たとえば、Scott Meyers:Copying Constructors in C++11を参照してください。クラス階層のない他の実装では、完全な転送コンストラクターがSFINAEを介したコピーコンストラクターにならないようにすることができます。たとえば、Martinho Fernandes:転送コンストラクターに関するいくつかの落とし穴を参照してください。上記の解決策をこの例に適用しようとすると、同じエラーメッセージでコンパイルできません。

考えられる解決策の1つは、完全な転送を回避し、コンストラクターでパラメーターを値で取得してから、それらからクラス変数に移動することだと思います。

だから私の質問は、この問題に対する他の解決策があるかどうか、またはそのような場合に完全な転送が不可能かどうかです。

更新: 私の質問は誤解されやすいことがわかりました。それで、私は私の意図と文脈を少し明確にしようとします。

  • コードは質問に投稿されたように完全です。作成された他のオブジェクトや呼び出された関数はありません。投稿された例をコンパイルしようとしたときにエラーが発生しました。
  • 完全な転送コンストラクターを持つことの目的は、メンバーの初期化であり、ある種の余分なコピーコンストラクターを持つことではありません。ここでの理由は、一時的なオブジェクトでメンバーを初期化するときにいくつかのオブジェクトのコピーを保存するためです(Scott Meyersによる講演で提案されたように)
  • 残念ながら、完全な転送コンストラクターは、他のオーバーロードされたコンストラクター(この例ではコピーコンストラクター)と競合する可能性があります。
  • 提案されたこの質問への回答とコメントのように:ここで考えられる解決策は、明示的なキャストを導入するか、テンプレート化されていないコンストラクターを個別に持つことです(つまり、それぞれパラメーターを持つ2つのコンストラクターを持つ例に関してconst string&string&&
0 投票する
2 に答える
7832 参照

c++ - 通常/常に std::move の代わりに std::forward を使用できますか?

私は、C++ and Beyond 2012 カンファレンスでのUniversal References に関する Scott Meyers の講演を見てきましたが、これまでのところすべてが理にかなっています。ただ、私も気になっていたところで、50分くらいで観客から質問が。Meyers は、答えは慣用的ではなく、頭がおかしくなるので気にしないと言いますが、私はまだ興味があります。

提示されたコードは次のとおりです。

要点は、右辺値参照を取得すると、右辺値があることがわかっているため、それが右辺値でstd::moveあるという事実を保持する必要があるということです。ユニバーサル参照 ( T&&、ここでTは推定型)を取得する場合std::forward、それが左辺値または右辺値である可能性があるという事実を保持したいと考えています。

問題はstd::forward、関数に渡された値が左辺値か右辺値かを保持し、std::moveその引数を右辺値にキャストするだけなので、std::forwardどこでも使用できるかということです。を使用するすべての場合とstd::forward同じように動作しますか、または Meyers の一般化によって見落とされている動作の重要な違いはありますか?std::movestd::move

マイヤーズが正しく言っているように、それは完全に慣用的ではありませんが、次のようにも の有効な使用法であるため、誰もがそれを行うべきだと示唆しているわけではありませんstd::move

0 投票する
1 に答える
114 参照

c++ - この例の移動と前進の違い

A を値で受け取る最初の例は 2 つの移動を行い、refref によるものは 1 つの移動のみを行います。違いはなんですか?

0 投票する
1 に答える
79 参照

c++ - コピー コンストラクターの転送に関する問題

転送コピー ctor が機能しない理由を知っている人はいますか?

1 つのタイプがベクターであり、他のタイプがスタックであるというコンパイラ エラー ???

0 投票する
1 に答える
3599 参照

c++ - C++で関数の名前を変更(エイリアス/転送)する最良の方法は何ですか?

(C++98 でこれを行う一般的な方法はないと思うので、この質問を C++11 に制限します)。

複雑な (シグネチャの観点から)テンプレート関数やオーバーロードされた関数のセットがあり、これらの関数をまったく同じ方法で使用したいが、別の名前 (つまり、エイリアス) を使用したいとします。

例えば:

ここで、これらの関数の名前を一度に変更(より正確にはalias、またはforward ) したいとします (つまり、同じ関数を書き換えずに別の名前を使用できるようにする)。そのため、コードの他の部分では、上記のコードを変更せずに別の名前で使用できます。

これは(エイリアス/転送)に名前を変更する正しい方法ですか?fungun

  • それは本当に一般的なものですか?
  • これは最も簡単な方法ですか?
  • これは最適な方法ですか?(例: インライン化可能、不要なコピーなし)
  • 元の関数にいくつかの SFINAE 機能があった場合はどうなるでしょうか? (例template<class A, class B, class C, class = std::enable_if< ... >::type>)、decltypeすべての場合に SFINAE を転送しますか?
  • 元の関数が参照を返すとどうなるでしょうか? decltype は参照型を削除しようとしていませんか? (例double& fun(double& x){return x;})。
  • メンバー関数についても同じことが言えますか?

明確化:インスタンスのアドレスが異なるため、 が正確gunになることは決してありませんが、私が探しているのは、汎用コーディングの観点からの名前変更です。 fun

コメント: ほとんどすべての名前変更/転送、名前空間、型 ( typedef) およびテンプレート型using typedefが可能であるのに、関数 (またはメンバー関数) ができないことは奇妙です。


編集:完全を期すために、これがそれを行う方法のように思われるため、ここで関数エイリアスを定義するマクロを追加しました:

そして、次のように使用します。


EDIT2:エイリアスにも例外ポリシーを組み込むことができると思います:

しかし、まだテストしていません。 3 回入力する必要があります

0 投票する
1 に答える
9123 参照

c++ - 非同期ラムダへの完全転送

別のスレッドで実行するラムダに完全に転送したい関数テンプレートがあります。以下は、直接コンパイルできる最小限のテスト ケースです。

コンパイルしていない場合のエラー メッセージの最後の行は次のとおりです。

の推定方法に関係があるのではないかと感じていますT&&が、正確な障害点を特定して修正することはできません。助言がありますか?

ありがとうございました!

編集:これがコンパイラの問題である可能性がある場合に備えて、gcc 4.7.0を使用しています(おそらくそうではありません)