2016-10-02 5 views
10

Betrachten Sie dieses Beispiel (also available on wandbox):Kann C++ 17 'automatisch' Nicht-Typ `Template'-Parameter Mustervergleichsvorlagen mit expliziten Nicht-Typ-Parametern ableiten?

template <template <auto> class> 
void test() { } 

template <int> 
struct X { }; 

Versuch test<X>() auf clang++ 4.0 (Stamm) führt zu einem Kompilierungsfehler zu instanziiert:

war
error: no matching function for call to 'test' 
    test<X>(); 
    ^~~~~~~ 

note: candidate template ignored: 
     invalid explicitly-specified argument for 1st template parameter 
void test() { } 

Meine anfängliche Annahme/Intuition, dass test könnte verwendet werden, um einen beliebigen template mit einem Nicht-Typparameter zu finden.


jedoch der folgende Code-Schnipsel erfolgreich kompiliert:

template <template <auto> class> 
void test() { } 

//  vvvv 
template <auto> 
struct X { }; 

Ist das beabsichtigt? Konnte nicht schlüssig in P0127R2 finden.

+0

Im Titel meintest du "abgeleitet"? –

Antwort

9

Es ist definitiv beabsichtigt. Vorlagenvorlagenparameter können nur Vorlagen entsprechen, die die gleichen Argumente haben. Dies:

template <template <auto> class> 
void test() { } 

kann nur mit einer Klasse-Vorlage instanziiert werden, die jede Art von Nicht-Typ-Parameter erfolgen kann. Aber das:

template <int> 
struct X { }; 

ist nicht so eine Klassenvorlage. X kann nur mit einem int instanziiert werden. Es stimmt einfach nicht mit der Spezifikation für den Vorlagenparameter überein, daher der Fehler. Was, wenn test seine Klassenvorlage mit einem Zeigertyp instanziieren wollte? Oder Zeiger auf Funktion oder Zeiger auf Mitglied? Das wäre unmöglich.

Ihr zweiter Versuch mit template <auto> struct X { };stimmt mit dem Template-Template-Parameter überein, ist also wohlgeformt. Beachten Sie auch, dass das Umgekehrte mit test einen template <int> class Parameter nehmen und in template <auto> struct X { }; übergeben wird, ist auch wohlgeformt, da das Argument allgemeiner als der Parameter ist.


Die entsprechende Formulierung ist in [temp.arg.template]:

A template-argument matches a template template-parameterP when each of the template parameters in the template-parameter-list of the template-argument’s corresponding class template or alias template A matches the corresponding template parameter in the template-parameter-list of P . Two template parameters match if they are of the same kind (type, non-type, template), for non-type template-parameters, their types are equivalent (14.5.6.1), and for template template-parameters, each of their corresponding template-parameters matches, recursively.


Hinweis: Die Gleichwertigkeit Wortlaut der auto akzeptiert - auto Fall und lehnt die auto - int Fall aber scheint auch den int - auto Fall abzulehnen (basierend auf meinem Lesen). Ich werde versuchen, Klarheit darüber zu bekommen.

+0

Ergebnis für Ihre Klärungsanfrage? –

+0

@ JohannesSchaub-litb [nein] (https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/xVUfSpP0_48) – Barry

2

Neben Barrys Antwort, die mich neugierig gemacht, hier sind die vier möglichen Kombinationen und Ergebnisse mit Clang 4.0 (SVN), see also on wandbox:

template <bool> struct obj_bool { }; // object taking a value of boolean type 
template <auto> struct obj_auto { }; // object taking a value of deduced type 
//  ^^^^^^ Note: this is a template value argument (non-type template argument) 

template <template <auto> typename> void fn_auto() { } 
template <template <bool> typename> void fn_bool() { } 
//  ^^^^^^^^^^^^^^^^^^^^^^^^ Note: this is a template type argument 
//     ^^^^^^    taking a template value argument 

int main() {  
    fn_bool<obj_bool>(); // #1 bool->bool OK (exact match) 
    fn_auto<obj_auto>(); // #2 auto->auto OK (exact match) 
    fn_bool<obj_auto>(); // #3 bool->auto OK (sub-set) 
    //fn_auto<obj_bool>(); // #4 auto->bool Error: no matching function. 
} 

Von diesen, # 1 und # 2 ist offensichtlich genau passt und funktioniert wie erwartet.# 3 würde die bool-Implementierung für eine Vorlage aufrufen, die nicht nur bool, sondern alle Typen verarbeiten kann, während # 4 versucht, eine Definition aufzurufen, die ein generalisiertes Objekt (auto) erwartet, wobei ein Objekt nur eine Untermenge (bool) von Möglichkeiten bietet .

Die Vorlagenfunktion fn_auto verspricht mögliche Instanziierungen für Vorlagen, die einen beliebigen Werttyp (auto) annehmen. Wenn man also nur eine Untermenge von Möglichkeiten (bool) gibt, verstößt diese Verheißung.

Obwohl nicht sofort offensichtlich, macht die Einschränkung Sinn. Und tut mir leid, dass meine Formulierungen nicht C++ Standard-konform sind.

Verwandte Themen