2017-12-17 9 views
5

は、我々は、ユーザー定義の控除のガイドと一緒に、このようなクラスがあるとしましょうガイド。演繹されたテンプレート引数とは何でしょうか?ユーザー定義の自動テンプレート控除対は、優先順位

いくつかの実験が行われた後、それはコンパイラによって異なります。すなわち、GCC 7と打ち鳴らす6(トランクから)は、空のパックとintArgsTをインスタンス化し、自動ガイドを選択するように見える、従って出力は

Args and T: Foo<T, Args>::Foo(Args&& ..., T&&) [with T = int; Args = {}] 

打ち鳴らす5であり、一方、選択

just Args: Foo<Void, int>::Foo(Args &&...) [T = Void, Args = <int>] 

どちらの選択肢が正しいか、この場合、どのようにユーザー定義の控除ガイドを使用するのですか?

wandboxで利用可能な完全な例。

答えて

3

最初の原則から始めましょう。 Foo{10}から推測しようとすると、このセットにオーバーロードの解決を行うことが含ま:最初のコンストラクタから合成機能で

template <typename T, typename... Args> 
Foo<T, Args...> __f(Args&&...); // ctor #1 

template <typename T, typename... Args> 
Foo<T, Args...> __f(Args&&..., T&&); // ctor #2 

template <typename... Args> 
Foo<Void, Args...> __f(Args&&...); // deduction guide 

は、Tが非推測コンテキストです。第2のコンストラクタから合成された関数では、Argsは推論されないコンテキストです。したがってどちらも実行可能ではありません。控除ガイドは実行可能ですので、最も有望な候補ですので、最終的にはFoo<Void, int>になります。

ここに来たら、再びオーバーロードの解決を実行してコンストラクタを選択します。これはより簡単で、最初のものは実行可能であり、2番目のものは実行されないので、呼び出される必要があります。

その他の動作は、コンパイラのバグ(83447)です。

+1

ctor#2から合成された関数で 'Args'が推論されないコンテキストになっているのはなぜですか?それは完全に信じられないようです:この特定のケースでは空のパックです。 – 0xd34df00d

+1

@ 0xd34f00d http://eel.is/c++draft/temp#deduct.type-5.7 – Barry

+0

右、私はバグレポートに表示されたものに近い簡単な例を投げてきました。すべてのgccを試してみましたが、5と6の両方がうまくいきましたので、正しいと思いました。あなたが与えたリンクはそれが証明していない!興味深いことに、clang <4はコードを拒否します。現時点では、既存のコンパイラでコードを動作させるために、ダミータグパラメータを2番目のctorに追加しました。これは、実装の詳細であり、クラスユーザーから呼び出されるべきではないからです。どうもありがとう! – 0xd34df00d

関連する問題