Was ist ein nicht abgeleiteter Kontext?

Lesezeit: 4 Minuten

Was ist ein nicht abgeleiteter
Schuh

Ich bin darüber gestolpert “Warum funktioniert der Template-Argumentabzug hier nicht?“ kürzlich und die Antworten lassen sich zu „Es ist ein nicht abgeleiteter Kontext“ zusammenfassen.

Insbesondere der erste sagt, dass es so ist, und leitet dann für “Details” zum Standard weiter, während der zweite den Standard zitiert, was gelinde gesagt kryptisch ist.

Kann jemand Normalsterblichen wie mir bitte erklären, was für eine nichtabgeleiteter Kontext ist, wann tritt es auf und warum tritt es auf?

  • Verwandte: C++, Template-Argument kann nicht abgeleitet werden

    – Shafik Yaghmour

    11. August 2014 um 14:22 Uhr

1647199807 267 Was ist ein nicht abgeleiteter
Kerrek SB

Abzug bezieht sich auf den Prozess der Bestimmung des Typs eines Vorlagenparameters aus einem gegebenen Argument. Es gilt für Funktionsvorlagen, auto, und einige andere Fälle (z. B. Teilspezialisierung). Betrachten Sie zum Beispiel:

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

Nun, wenn Sie sagen f(x)wo Sie erklärt haben std::vector<int> x;dann T ist abgeleitet als intund Sie erhalten die Spezialisierung f<int>.

Damit die Ableitung funktioniert, muss der abzuleitende Vorlagenparametertyp in einem ableitenden Kontext erscheinen. In diesem Beispiel ist der Funktionsparameter von f ist solch ein deduzierbarer Kontext. Das heißt, ein Argument im Funktionsaufrufausdruck ermöglicht es uns, den Vorlagenparameter zu bestimmen T sollte sein, damit der Aufrufausdruck gültig ist.

Allerdings gibt es auch nicht-abgeleitete Kontexte, in denen keine Ableitung möglich ist. Das kanonische Beispiel ist „ein Vorlagenparameter, der links von a erscheint :::

template <typename> struct Foo;

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

In dieser Funktionsvorlage wird die T in der Funktionsparameterliste befindet sich in einem nicht abgeleiteten Kontext. So kann man das nicht sagen g(x) und ableiten T. Der Grund dafür ist, dass zwischen beliebigen Typen und keine “Rückwärtskorrespondenz” besteht Mitglieder Foo<T>::type. Zum Beispiel könnten Sie Spezialisierungen haben:

 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>  { };

Wenn Sie anrufen g(double{}) es gibt zwei mögliche Antworten für Tund wenn Sie anrufen g(int{}) Es gibt keine Antwort. Im Allgemeinen gibt es keine Beziehung zwischen Klassenvorlagenparametern und Klassenmitgliedern, sodass Sie keine vernünftige Argumentableitung durchführen können.


Gelegentlich ist es sinnvoll, die Argumentableitung explizit zu unterbinden. Dies ist beispielsweise der Fall bei std::forward. Ein weiteres Beispiel ist, wenn Sie Conversions von haben Foo<U> zu Foo<T>sagen wir, oder andere Konvertierungen (think std::string und char const *). Angenommen, Sie haben eine freie Funktion:

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

Wenn Sie anrufen binary_function(t, u), dann kann die Deduktion mehrdeutig sein und somit scheitern. Aber es ist vernünftig, nur ein Argument und abzuleiten nicht den anderen ableiten und so implizite Konvertierungen zulassen. Jetzt wird ein explizit nicht abgeleiteter Kontext benötigt, zum Beispiel so:

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);
}

(Möglicherweise haben Sie solche Abzugsprobleme mit etwas wie erlebt std::min(1U, 2L).)

  • Sie beziehen sich also auf den zweiten vom Standard beschriebenen Fall (“Ein Typ, der eine Vorlagen-ID ist, in der eines oder mehrere der Vorlagenargumente ein Ausdruck ist, der auf einen Vorlagenparameter verweist.”), richtig? Wenn ja, können Sie ein Beispiel für den ersten geben (“Der verschachtelte Namensbezeichner eines Typs, der mit einer qualifizierten ID angegeben wurde.”)?

    – Schuh

    11. August 2014 um 14:32 Uhr

  • Jetzt, wo ich es sorgfältig lese, denke ich eigentlich, dass es das Gegenteil ist.

    – Schuh

    11. August 2014 um 14:33 Uhr


  • @ Jeffrey: Vielleicht so etwas wie template <std::size_t> struct Bar; template <typename T> void(Bar<sizeof(T)>);?

    – Kerrek SB

    11. August 2014 um 14:36 ​​Uhr


  • Der Punkt ist folgender: Es gibt eine Eins-zu-Eins-Entsprechung zwischen Typen T und Vorlagenklassen Foo<T>, also kannst du ersteres von letzterem ableiten. Aber da ist Nein Korrespondenz zwischen Typen T und willkürliche Mitglieder Foo<T>::X.

    – Kerrek SB

    11. August 2014 um 14:38 Uhr

  • Ich denke, du könntest das auch beantworten.

    – Baum mit Augen

    11. August 2014 um 14:48 Uhr

998820cookie-checkWas ist ein nicht abgeleiteter Kontext?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy