Dies ist gcc bug 80871. Was folgt, ist eine Erklärung dafür, warum der Code wohlgeformt ist (und es ist richtig zu entscheiden, dass t2
ein custom_tuple<int>
ist).
Der Prozess, herauszufinden, was mit
custom_tuple t2(42);
im Grunde eine Reihe von Funktionen beinhaltet zu tun zu synthetisieren und auf ihnen die Überladungsauflösung durchführen. Die entsprechenden Kandidaten sind die synthetisierten Funktionen aus dem einem Konstruktor und der Abzug Führung:
template <class... T, class... Args>
custom_tuple<T...> foo(Args...); // the constructor
template <class... Args>
custom_tuple<Args...> foo(Args...); // the deduction guide
Von diesem Punkt ist es ein auf der Grundlage Ihrer Interpretation Ihre eigenen Abenteuer wählen, was ein „nachlauf Parameter Pack“ wird nach [temp.arg.explicit]/3:
Ein nachfolgendes Template-Parameterpaket, das nicht anderweitig abgeleitet ist, wird auf eine leere Sequenz von Template-Argumenten zurückgeführt. Wenn alle Vorlagenargumente abgeleitet werden können, können sie alle weggelassen werden; In diesem Fall kann auch die leere Vorlagenargumentliste <>
selbst weggelassen werden.
T...
schleppt nicht
Dieser Fall ist einfach. Wir haben nur einen brauchbaren Kandidaten (weil T...
nicht ableitbar ist) - der Deduktionsleitkandidat. Wir leiten Args...
als {int}
ab, also enden wir mit custom_tuple<int>
.
T...
nachläuft
Beide gcc und Klirren tatsächlich Abzug betrachten für den Konstruktor erfolgreich zu sein. Also gehen wir zu den Tiebreaker in [over.match.best]:
diese Definitionen gegeben, eine tragfähige Funktion F1
ist definiert als ein besser Funktion als eine andere tragfähige Funktion F2
wenn [...]
F1
sein und F2
sind Funktionsvorlagenspezialisierungen, und die Funktionsvorlage für F1
ist spezialisierter als die Vorlage für F2
gemäß den Teilordnungsregeln, die in [temp.func.order] beschrieben sind, oder, falls nicht,
F1
wird aus einem Deduction-Guide ([over.match.class.educt]) generiert und F2
ist nicht, oder, wenn nicht das, [...]
Für die Zwecke der partiellen Ordnung, sind die relevant types Parameter solche, die nur entsprechen funktionieren, und wir sind zu ignore unused template parameters erlaubt, so dass die anderen weder Funktionsvorlage gilt als spezialisierter als.
Dies lässt uns einfach den Deduktionsführer bevorzugen, der der einfachste Schritt dieses ganzen Prozesses war. Wir leiten Args...
als {int}
ab, also enden wir mit custom_tuple<int>
.
Wie auch immer, custom_tuple<int>
ist die richtige Entscheidung.
Hmm, GCC und Clang Stamm nicht einverstanden auf OP-Code, und ich bin hier nicht wirklich überzeugt. Erstens, ist "T" "nach"? (Das ist ein ziemlich unbestimmter Begriff.) Zweitens, können Sie demonstrieren, wie der Konstruktor spezialisierter ist als der Deduktionsleitfaden? –
@ T.C. Aber cool zu sehen, wie Clang mit Deduktions-Guides arbeitet! Das muss ziemlich neu sein. – Barry
Der Kontext hier ist ein Funktionsaufruf, also ["die verwendeten Typen \ [für die partielle Sortierung \] sind diejenigen Funktionsparameter, für die der Funktionsaufruf Argumente hat"] (https://timsong-cpp.github.io/cppwp /temp.deduct.partial#3.1). Und für partielle Bestellzwecke kann [ein Vorlagenparameter ohne einen Wert bleiben, vorausgesetzt, er wird nicht in den Typen verwendet, die für die teilweise Bestellung verwendet werden] (https://timsong-cpp.github.io/cppwp/temp.deduct. Teil # 12) und 'T ...' ist nicht. Also genau wie ist einer spezialisierter als der andere? In welche Richtung scheitert der Abzug und wie? –