2016-12-22 11 views
1

が動作していない:C++テンプレート控除は、次のコードの場合

#include<functional> 
template<typename T> 
void f(std::function<void(T)> g) { 
} 

template<typename T> 
void g(T x) { 
} 

int main() { 
    f(&g<int>); 
} 

C++ 14コンパイラはエラーを生成します。

no matching function for call to 'f(<unresolved overloaded function type>)' 
    f(&g<int>); 

テンプレート引数控除はここで働いていない理由を私は好奇心旺盛です。 グラムの引数はint型であることを考えると、我々は、Fの引数は、それゆえT = int Fで、タイプstd::function<void(int)>のものであり、と推論することができ、ということらしいです。なぜこれは起こりませんか?私はこれを説明するC++標準の関連セクションに興味があります。 Tは、ここでは推論されていない状況で発生するか?

次のようなコードはコンパイルされます。

#include<vector> 
template<typename T> 
void f(std::vector<T> vec) { 
} 


int main() { 
    f(std::vector<int>{}); 
} 

だから、非推定されるコンテキストを作成して角括弧ではありません。

+0

'f(標準::機能(g ));' 作品 – xis

+0

ありがとう、ありがとう。実際には、f (&g );同様に動作します。私の問題は、標準で書かれていることに基づいてこれらの動作を説明することができないことです。 –

答えて

8

あなたの機能はタイプstd::functionの引数を期待していますが、それを代わりに関数へのポインタを渡しています。 &g<int>です。std::functionパラメータタイプですが、テンプレート引数の控除には完全一致が必要です(調整は[temp.deduct.call]/2,3,4で許可されています)。ただし、ユーザー定義のコンバージョンは考慮されません。

std::functionを渡しているので、f(std::function<void(int)>(g<int>))を書くと、テンプレート引数の控除が成功します。

f<int>(&g<int>)は明示的にTと指定されているため、テンプレート引数の控除に参加しなくなり、ユーザー定義の変換が試行されるようになりました。

+0

ありがとう!意味あり!私は議論の控除が「正確な」マッチを必要とするとは思わない。例えば、私が2番目の例でfの引数の型に "const"を追加すると、それはまだコンパイルされます。だから、私はいくつかの変換が許可されていると思います。 @Evgenii。 –

+0

。Balaiええ、私は少しあまりそれを簡略化:)今修正されました。 – Praetorian

+1

@ Evgenii.Balai:引数型の最上位の 'const'は関数シグネチャの一部ではないので、その場合でもまだ一致します。正確に一致しないものは参考になります。 – celtschk

2

&g<int>のタイプはvoid(*)(int)です。したがって、コンパイラは、テンプレートからは実行できないシグニチャvoid f<>(void(*)(int))の関数を生成しようとします。タイプstd::function<void(int)>は完全に異なるタイプです。あなたのようなコードで

、オブジェクトstd::vector<int>{}std::vector<int>のタイプのものであり、従ってコンパイラはintことがTを推定することにより供給されるテンプレートから行うことができる機能void f<>(std::vector<int>)を生成しようとします。

f<int>を指定すると、コンパイラはその型を推論する必要がないため、そのようにすることはできません。さらに、推論された文脈では暗黙的な変換は考慮されないが、は非推論文脈ではと考えられる。したがって、型を明示的に指定して関数の引数を推論しないコンテキストにすることで、コンパイラは暗黙の変換を使用してstd::function<void(int)>引数をg<int>で初期化できます。

関連する問題