Die Diskussion um NTTP (non-type template parameter) scheint nun beendet
zu sein. Leider ist da
https://en.cppreference.com/w/cpp/language/template_parameters
nicht ganz auf dem letzten Stand.
In den Papern P0732, P1185 und nun P1907 wurde die ganze Sache gerade
gezogen, leider mit dem Ergebnis, dass die Typen der NTTP sog.
structural sein müssen, was wiederum bedeutet, dass alle Datenelemente
public sein müssen. Das finde ich schade, weil bspw. auch
std::chrono::duration damit herausfällt (und auch einige meiner eigenen
Klassentemplates).
1
#include<cstdint>
2
#include<cstdlib>
3
#include<type_traits>
4
#include<chrono>
5
#if __has_include("compare")
6
# include <compare>
7
#endif
8
9
template<autoV>structA{};
10
11
#if (__GNUC__ <= 9)
12
structB{
13
constexprexplicitB(inta):value{a}{}
14
private:
15
constintvalue{0};
16
};
17
#endif
18
19
#if (__GNUC__ > 9)
20
structB{
21
constexprexplicitB(inta):value{a}{}
22
constexprautooperator<=>(constB&)const=default;
23
// to be structural all members have to be public and structural as well
Ich warte ja noch bis jemand eine Sprache in C++ einbettet die
Turing-complete die Generierung von C++ - Code erlaubt.
Oder geht das mit Templates jetzt schon ;-)
Guest schrieb:> Oder geht das mit Templates jetzt schon ;-)
Templates für sich genommen sind Turing-vollständig.
Macht die Sprache(n) aber auch nicht schöner.
Guest schrieb:> Ich warte ja noch bis jemand eine Sprache in C++ einbettet die> Turing-complete die Generierung von C++ - Code erlaubt.
Der Beweis:
http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=0BB30D6BBA62A9F8054337264062C075?doi=10.1.1.14.3670&rep=rep1&type=pdf
Das template-Subsystem formt eine compile-time funktionale Sprache.
Damit kann man Abbildungen (Funktionen) der Formen:
1) compile-time-constant -> compile-time-constant
2) compile-time-constant -> type
3) type -> compile-time-constant
4) type -> type
durchführen. Wobei man für 1) ganz einfach auch constexpr / consteval
"normale" Funktionen benutzen kann/sollte. Boost-Hana als
Meta-Programm-Bibliothek erledigt auch 2) - 3) mit constexpr-Funktionen.
2.Attempt to develop the technology required for compiler and linkers to verify thatuser-defined equality operators are self-consistent and evaluate them, or3.Only allow non-type template parameters of class type for classes which havememberwise equality
2
If a template argument is a value of class type, then how do we mangle it into symbolnames? If we cannot, then how does the linker tell whether two template arguments ofclass type are the same? By default, class types do not even have a notion of equality.If we disregard unions, we could say that classes are simply compared memberwise for the purposes of template instantiation. However, doing this would break the invariant that &i<a> == &i<b> if and only if a == b : the latter may not even be valid, and if it is then it would only give the same results as the former if the relevant operator== implemented the same memberwise comparison that we used for the purposes of template instantiation.To resolve this question, we must either:
3
1.Allow the existing invariant to be broken, and accept the complexity and subtletiesadded to the language by doing this, or
4
2.Attempt to develop the technology required for compiler and linkers to verify that user-defined equality operators are self-consistent and evaluate them, or
5
3.Only allow non-type template parameters of class type for classes which have memberwise equality
6
7
This paper proposes pursuing the last of these options...
Ich kann nicht sagen, dass ich das nachvollziehen könnte.
Was spricht gegen das naive "constexpr operator==, wenn der nicht
richtig funktioniert ist es halt UB"?
Heiko L. schrieb:> Was spricht gegen das naive "constexpr operator==, wenn der nicht> richtig funktioniert ist es halt UB"?
Gott bewahre: nicht noch mehr davon!
Ich bin kein Compilerbauer und ich habe großen Respekt vor diesen Mädels
und Jungs. Deswegen ist meine Antwort hier nur laienhaft:
1) Das bisherige Modell der getrennten Übersetzungseinheiten soll
beibehalten werden
2) Aus 1) folgt, dass der Linker template-ids vergleichen können muss.
3) Für 2) wird bei NTTP deren Bit-Repräsentation als Wert in die
template-id verwurschtelt (mangled)
4) Die Bit-Repräsentation eines class-type NTTP ist Summe der
Bit-Repräsentationen der member.
5) Das ist identisch mit einer Gleichheitsdefinition von class-type
NTTP, die auf allen ihren membern basiert.
6) Ein op== müsste dazu auf jeden Fall dazu konsistent implementiert
werden.
7) Man kann 6) für user-defined op= nicht sicher stellen
8) Daher erzwingt man 6) durch den Verzicht auf Klasseninvarianten durch
all-public member, d.h. der beobachtbare Zustand eines Typs sind alle(!)
member, daher ist die Gleichheit zweiter Objekte durch einen
elementweisen Vergleich gegeben.
Bottom-line: man bräuchte eine konsistente Abbildung des Objektzustandes
(Werte) in eine template-id. Dazu ist für C++23 ein "operator template"
vorgeschlagen. Wie man für den dann allerdings die Konsistenz mit op==
bzw. op<=> sicherstellen will, ist mir noch nicht klar. Man läuft dann
in dasselbe Problem wie bei Java mit equals() und hashCode().
Das ist eine "Lösung", die eben bestimmte Typen ausschließt, aber
ansonsten in das bisherige Modell passt, ohne neue Schwierigkeiten
einzubauen.
Wilhelm M. schrieb:> Das ist eine "Lösung", die eben bestimmte Typen ausschließt, aber> ansonsten in das bisherige Modell passt, ohne neue Schwierigkeiten> einzubauen.
Naja, enttäuschend ist das Ergebnis aber schon. Unter den
Einschränkungen ist das Feature schon fast nicht zu gebrauchen.
Vielleicht hätte man deswegen von vornherein darauf verzichten und alles
von Anfang an nur über den operator regeln. Das ganze Problem wäre dann
nur syntactic sugar. Statt zu schreiben someClass<template_hash(x)>
hätte man someClass<x> und könnte alles frei überladen.
bottom-line: Das "Feature" werde ich vermutlich nicht nutzen, bis es
richtig funktioniert, so mit normalen Klassen und so.
Aber danke für die Erklärung.
Heiko L. schrieb:> bottom-line: Das "Feature" werde ich vermutlich nicht nutzen, bis es> richtig funktioniert, so mit normalen Klassen und so.
Na, so schlimm ist es auch wieder nicht: es sind dann einfach Typen ohne
Klasseninvarianten bzw. immutables.
Vieles davon könnte man ersetzen durch constexpr-Funktionsparameter.
Auch dazu gibt es einen Vorschlag.
Eine eigene Frage?
Dieser Thread ist über 6 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.