Standardargumente für Vorlagen

150

Wenn ich Folgendes tun darf:

template <typename T = int>
class Foo{
};

Warum darf ich hauptsächlich nicht folgendes tun?

Foo me;

Aber ich muss folgendes angeben:

Foo<int> me;

In C ++ 11 wurden Standardvorlagenargumente eingeführt, die meines Erachtens derzeit nur schwer zu verstehen sind.

user633658
quelle

Antworten:

188

Du musst:

Foo<> me;

Die Vorlagenargumente müssen vorhanden sein, können jedoch leer gelassen werden.

Stellen Sie sich das wie eine Funktion foomit einem einzigen Standardargument vor. Der Ausdruck foowird es nicht nennen, aber foo()wird. Die Argumentsyntax muss noch vorhanden sein. Dies steht im Einklang damit.

Joseph Mansfield
quelle
4
@Pubby Ich nehme an, es würde einige unnötige Komplikationen verursachen , wenn Foo vielleicht eine Vorlage Bezeichner sein oder könnte eine explizite Instanziierung in Abhängigkeit davon, ob ein Standardargument gibt. Behalten Sie besser die explizite Instanziierungssyntax bei. Stellen Sie sich das wie eine Funktion foomit einem einzigen Standardparameter vor. Sie können es nicht so nennen foo, Sie nennen es mit foo(). Es ist sinnvoll, dies konsistent zu halten.
Joseph Mansfield
2
@sftrabbit, aber Sie können keine Funktion ohne Argumente wie diese aufrufen foo. Sie können jedoch eine Klasse ohne Argumente benennen Foo.
Seth Carnegie
4
@aschepler Mit einer Funktion können die Vorlagenargumente aus den Funktionsargumenten abgeleitet werden. Bei einer Klasse kann nicht entschieden werden, ob Sie eine Vorlagenklasse mit Standardargumenten oder eine Nicht-Vorlagenklasse gemeint haben.
Olaf Dietsche
21
@OlafDietsche, aber Sie können keine Vorlagenklasse und keine Nicht-Vorlagenklasse mit demselben Namen haben, daher sollte der Compiler in der Lage sein, zu entscheiden, indem er sich nur den Namen ansieht.
Seth Carnegie
7
@Pubby Das Standardkomitee hat sich das auch gefragt, denke ich. Mit C ++ 17 <>ist dies in diesem Fall nicht mehr erforderlich. Schauen Sie sich meine Antwort für weitere Details an.
Paolo M
53

Mit C ++ 17 können Sie in der Tat.

Diese Funktion wird als Ableitung von Klassenvorlagenargumenten bezeichnet und bietet mehr Flexibilität bei der Deklaration von Variablen mit Vorlagentypen .

So,

template <typename T = int>
class Foo{};

int main() {
    Foo f;
}

ist jetzt legaler C ++ - Code .

Paolo M.
quelle
5
Seltsam. Ich habe es gerade in meinem C ++ 17-Projekt versucht und es hat nicht funktioniert: "Template-Platzhaltertyp 'const MyType' muss von einer einfachen Deklarator-ID gefolgt werden". Ich benutze GCC 7.3.0.
Silicomancer
1
@ Silicomancer Es ist schwer zu sagen, ohne Ihren Code und Ihre Befehlszeile zu sehen ... Vielleicht haben Sie es mit Zeigern wie hier zu tun ?
Paolo M
1
Clang akzeptiert es nicht, wie es scheint? coliru.stacked-crooked.com/a/c5d3c0f90ed263c2
Borgleader
1
@ Borgleader Anscheinend verwendet Coliru Clang 5.0. Gemessen an diese , sollte es unterstützen 17 Template - Argument Abzug C ++, aber offenbar ID nicht. Wenn Sie dasselbe Beispiel in der Zauberbox mit Clang 7.0 ausprobieren , funktioniert es einwandfrei.
Paolo M
2
@PaoloM Oh cool, ich bin froh zu wissen, dass es sich nur um ein Compiler-Versionsproblem handelt. Vielen Dank, dass Sie sich damit befasst haben.
Borgleader
19

Das darfst du nicht, aber das kannst du

typedef Foo<> Fooo;

und dann tun

Fooo me;
g24l
quelle
Gibt es einen Unterschied zwischen einem Standardtyp und: typedef Foo<float> Fooo;ohne Standardtyp?
Qrikko
5
Der C ++ 11-ish Weg wäre zu sagenusing Fooo = Foo<>;
Adrian W
18

Sie können Folgendes verwenden:

Foo<> me;

Und intsei dein Vorlagenargument. Die eckigen Klammern sind notwendig und können nicht weggelassen werden.

Andy Prowl
quelle
Sinnvoll und danke, aber wie unten angegeben, warum muss der angegebene Typ nicht vorhanden sein?
user633658
@ user633658: Meinten Sie "Typspezifizierer"? Ich bin nicht sicher, ob ich es verstehe
Andy Prowl
Was den Grund für die Notwendigkeit leerer eckiger Klammern angeht, kann ich nur Vermutungen anstellen, und es geht darum, mögliche Unklarheiten bei der Verwendung des Namens der Vorlage allein auszuschließen, aber ich muss gestehen, dass ich das genaue nicht kenne Grund
Andy Prowl
Ich vermute sehr, dass die Anforderung für das <> darin besteht, dass der Parser des Compilers feststellen kann, dass Sie sich auf eine Vorlagenklasse namens foo beziehen, anstatt auf etwas anderes namens foo.
Mac