1. ホーム
  2. c++

無教養な文脈とは?

2023-09-21 01:21:14

質問

"でつまずいたことがあります。 ここでは、なぜテンプレート引数deductionが機能しないのでしょうか? "最近、答えは "無教養な文脈です"に集約されるようになりました。

具体的には、最初のものはそのようなものだと言って、"詳細"のために標準にリダイレクトし、2番目のものは標準を引用しており、はっきり言って意味不明です。

誰か、私のような凡人に対して 非教養的なコンテキスト とは何か、それはいつ起こるのか、そしてなぜ起こるのか。

どのように解決するのですか?

控除 は、与えられた引数からテンプレートパラメータの型を決定するプロセスを指します。これは関数テンプレートに適用されます。 auto そして、他のいくつかのケース(例えば、部分的な特殊化)にも適用されます。例えば、考えてみましょう。

template <typename T> void f(std::vector<T>);

ここで、もしあなたが f(x) と宣言した場合、ここで std::vector<int> x; と宣言した場合、次に T と推論される。 として int となり、特殊化された f<int> .

演繹が機能するためには、演繹されるテンプレートパラメータ型が演繹可能なコンテキストに出現していなければなりません。この例では、関数パラメータである f がそのような推論可能なコンテキストです。つまり、関数呼び出し式の引数によって、テンプレートパラメタ T は何であるべきかを決定することができます。

しかし、この他に 以外の -のコンテキストもあり、そこでは演繹は不可能です。典型的な例として、" の左側に表示されるテンプレート パラメータがあります。 :: :

template <typename> struct Foo;

template <typename T> void g(typename Foo<T>::type);

この関数テンプレートでは T は非教育的な文脈にあります。したがって、次のように言うことはできません。 g(x) と言って T . この理由は、任意の型と メンバー Foo<T>::type . 例えば、specializationを持つことができます。

 template <> struct Foo<int>       { using type = double; };
 template <> struct Foo<char>      { using type = double; };
 template <> struct Foo<float>     { using type = bool; };
 template <> struct Foo<long>      { int type = 10; };
 template <> struct Foo<unsigned>  { };

もしあなたが g(double{}) には二つの可能な答えがあります。 T を呼び出すと g(int{}) を呼び出しても答えはありません。一般に、クラス・テンプレートのパラメータとクラス・メンバの間には何の関係もありませんから、賢明な引数演繹は行えません。


時には、明示的に引数演繹を禁止することが有用な場合があります。これは例えば std::forward . からの変換がある場合です。 Foo<U> から Foo<T> と言うように、その他の変換(例えば std::stringchar const * ). ここで、自由関数があるとします。

template <typename T> bool binary_function(Foo<T> lhs, Foo<T> rhs);

もしあなたが binary_function(t, u) を呼び出すと、推論が曖昧になり、その結果失敗する可能性があります。しかし、1つの引数だけを推論するのは合理的であり ではなく を推論することは合理的であり,暗黙の変換を許容する。ここで明示的に推論されないコンテキストが必要となり、例えばこのようになります。

template <typename T>
struct type_identity {
    using type = T;
};

template <typename T>
bool binary_function(Foo<T> lhs, typename type_identity<Foo<T>>::type rhs)
{
    return binary_function(lhs, rhs);
}

(のようなもので、このような控除問題を経験したことがあるかもしれません)。 std::min(1U, 2L) .)