次のコードを検討してください。
_template <typename>
struct S { };
void g(S<int> t);
template <typename T>
void f(T, std::function<void(S<T>)>);
_
呼び出そうとしたとき
_f(0, g);
_
次のエラーが発生します。
_error: no matching function for call to 'f' f(0, g); ^ note: candidate template ignored: could not match 'function<void (S<type-parameter-0-0>)>' against 'void (*)(S<int>)' void f(T, std::function<void(S<T>)>); ^
_
_std::function
_パラメータのタイプは推定されないコンテキストであるため、一般的には推定できないことを理解しています
この場合、T
は最初に渡された引数_0
_から推定でき、次にstd::function<void(S<T>)>
に代入してstd::function<void(S<int>)>
を取得できます。
_T=int
_を推定した後、コンパイラーはシグニチャーのすべての場所でT
を代入し、引数g
を使用して_std::function
_パラメーターを構築しようとするでしょう。
そうではないのはなぜですか?置換/演繹が行われる順序はこれと関係があると思いますが、見たいのですが関連する標準的な文言。
ボーナス質問:これは、下位互換性を維持しながら将来の標準で変更される可能性があるものですか、またはこの種の置換が機能しない根本的な理由はありますか?
Std :: functionパラメータのタイプは推定されていないコンテキストであるため、一般的には推定できないことを理解しています。
これは非推論のコンテキストではありません。全く逆です。 std::function
のパラメーターの演繹が試みられますが、引数はstd::function
ではないであるため、演繹は失敗します。関数の引数からテンプレートの引数を差し引くと、すべての関数の引数が一致する必要があります。 1つ失敗すると、完全に失敗します。
[temp.deduct.type]
2 場合によっては、タイプPおよびAの単一のセットを使用して演繹が行われます。他の場合には、対応するタイプPおよびAのセットが存在します。タイプの演繹は、各Pに対して独立して行われます/ Aペア、および推定されたテンプレート引数値が結合されます。 P/Aペアで型の推論を実行できない場合、またはいずれかのペアで推論により、推定値の複数のセットが生成される場合、または異なるペアが異なる推定値を生成する場合、またはテンプレート引数が推定値でも明示的にも残っていない場合指定すると、テンプレート引数の推定は失敗します。
2番目の関数パラメーターの型を非推論コンテキストにすることは、実際にはエラーを克服する方法です。
#include <functional>
template<typename T>
struct type_identity {
using type = T;
};
template <typename>
struct S { };
void g(S<int> ) {}
template <typename T>
void f(T, typename type_identity<std::function<void(S<T>)>>::type) {}
int main() {
f(0, g);
}
T
は最初の関数引数から正常に推定され、推定するものは何も残っていません。したがって、この献身は成功と見なされます。
std::function
パラメータのタイプは、推定されていないコンテキストであるため、一般に推定できないことを理解していますが、この場合、T
は、渡された引数0
によって最初に推定できます。
本当じゃない。 T
は、このコンテキストでは推定可能です。コードを次のように変更した場合
template <typename T>
void f(std::function<void(S<T>)>);
int main()
{
f(std::function<void(S<int>)>(g));
}
コードがコンパイルされ、T
が正しく推定されます。
あなたの問題は、T
を抽出できない関数にオブジェクトを渡そうとしていることです。コンパイラは、T
を推定しようとするときに、関数の引数の変換を行いません。これは、関数に渡される型としてint
と関数があることを意味します。 0
からint
を取得し、2番目のパラメーターで渡したstd::function
から型を取得しようとしますが、std::function
を渡していないため、T
を抽出できません。 、エラーが発生します。