2017-08-22 10 views
9

関数引数の暗黙的なインスタンス化の仕組みを理解しようとしています。何らかの理由で、最初の例では、bar()コールは、{12,41}をイニシャライザリストとして解釈します。 fooの署名をauto foo(std::pair<int,int> bar)に変更すると、{12,41}は暗黙的にstd::pair<int,int>に変換されます。関数引数の暗黙的なインスタンス化

template<typename T, typename U> 
auto foo(std::pair<T,U> arg) { return arg; } 
auto bar()     { return foo({12,41}); } 

例えば

はエラーで失敗します。

<source>: In function 'auto bar()': 
104 : <source>:104:50: error: no matching function for call to 'foo(<brace-enclosed initializer list>)' 
auto bar()     { return foo({12,41}); } 
               ^
103 : <source>:103:6: note: candidate: 'template<class T, class U> auto foo(std::pair<_T1, _T2>)' 
auto foo(std::pair<T,U> arg) { return arg; } 
     ^~~ 
103 : <source>:103:6: note: template argument deduction/substitution failed: 
104 : <source>:104:50: note: couldn't deduce template parameter 'T' 
auto bar()     { return foo({12,41}); } 
               ^

しかし

auto foo(std::pair<int,int> arg) { return arg; } 
auto bar()      { return foo({12,41}); } 

作品を。なぜ誰かが精巧に考えていますか?

答えて

13

通常の理由から、暗黙的な変換は、テンプレート化された関数と同じ方法(またはまったく)で起こらない傾向があります。あなたの2番目の例で:

auto foo(std::pair<int,int> arg) { return arg; } 
auto works()      { return foo({12,41}); } 

fooは関数テンプレートではなく、関数です。 std::pairには、明示的ではない2つの引数コンストラクタ、http://en.cppreference.com/w/cpp/utility/pair/pairがあります。 n個のエントリを持つ中括弧パックは、暗黙的にn個の暗黙のコンストラクタを持つ型に暗黙的に変換できます。したがって、{12,31}からstd::pair<int, int>へ暗黙的に変換されます。

関数テンプレートが呼び出されると、テンプレートの控除によって引数が一致するようにテンプレートが推測されます。このプロセスでは、暗黙的な変換の全範囲を使用できません。非常に特別なコンバージョンのみが許可されます:http://en.cppreference.com/w/cpp/language/template_argument_deduction。基本的には、CV変換、派生から基本への変換、およびいくつかのポインタ修飾と関数ポインタ変換です。

ので:fooが呼び出されたとき、それは呼び出しの引数とパラメータが一致するためにfooにテンプレートパラメータを代用しようとしますが、彼らは正確に十分に一致させることができないため、

template <class T, class U> 
auto foo(std::pair<T, U> arg) { return arg; } 
auto bar()     { return foo({12,41}); } 

は、失敗。

私はpair<auto, auto>の構文にはコメントしていませんが、より明示的な構文と状況はまったく同じですので、本当に問題の中心ではないと思います。

これについては、ここでこれまでに議論しています。C++ implicit type conversion with templateですので、詳細はお読みください。ただし、関数テンプレートと一致する場合は、CVの変更が許可されているだけであるという誤った回答があることに注意してください。それはかなり真実ではない(おそらく私はそこに編集を提案するだろう)。

関連する問題