Waarom kunnen constructeurs geen sjabloonargumenten afleiden?

In de bovenstaande code klaagt de compiler dat sjabloonargumenten vóór ‘f’ ontbreken. Ik begrijp dat het afleiden van sjabloonargumenten voor een klasse uit de argumenten voor de constructor geen deel uitmaakt van de standaard, maar mijn vraag is waarom? Heeft de compiler niet alle informatie die hij nodig heeft om impliciet Foo<int>te instantiëren en zijn constructor aan te roepen?

Bewerkt om duidelijk te maken dat ik de constructor aanroep met een int(in tegenstelling tot een short, long, void*, enz.)


Antwoord 1, autoriteit 100%

Omdat niemand heeft gespecificeerd hoe dat precies werkt. Er is een huidig ​​voorstel aan de standaardcommissie om het te laten werken. Het somt ook enkele van de moeilijkheden op:

http://open-std.org/ JTC1/SC22/WG21/docs/papers/2015/n4471.html

Update: hier is de nieuwste versie van het voorstel:

http://open-std.org/ JTC1/SC22/WG21/docs/papers/2015/p0091r0.html


Antwoord 2, autoriteit 50%

TL;DR: Sjabloonspecialisatie


Dat kunnen ze, maar alleen sjabloonargumenten voor de functie zelf, niet voor het type.

De declaratie Foo f(0);is illegaal, omdat er geen type is met de naam Foo. Misschien dacht je aan

auto f = Foo(0);

maar dat mag ook niet, omdat de compiler niet weet in welk bereik hij moet zoeken (er zijn oneindig veel potentiële typen met een constructor genaamd Fooen, met specialisatie, mogelijk meer dan één met een constructor Foo(int))

De gebruikelijke methode om dit te doen is met een fabriekshelperfunctie:

auto f = make_foo(0);

waar het retourtype van de fabrieksfunctie afhangt van de typeaftrek van de parameters.


Je kunt je voorstellen dat de fabrieksfuncties automatisch kunnen worden gegenereerd in het bereik van de naamruimte en dat vervolgens de gebruikelijke regels voor functieoverbelasting worden toegepast, maar dit levert grote problemen op omdat er sjabloonargumenten kunnen zijn voor zowel het type als de constructor zelf. Deze zouden eenvoudig aaneengeschakeld kunnen worden, met de beperking dat dit klassensjablonen met variadische argumentlijsten zou uitsluiten, omdat er geen manier zou zijn om te onderscheiden waar de typeparameters eindigen en de functieparameters beginnen.


Antwoord 3, autoriteit 22%

Foois een klasse sjabloon, geen klasse. Het type moet altijd op de een of andere manier worden opgegeven om een ​​klasse met de juiste typen te genereren. Je kunt Fooniet doen omdat Foogeen type is, maar Foo<int>wel. Het creëert een klasse als volgt:

class Foo {
public:
  Foo( int t ) { }
};

Als je alleen Foohad opgegeven, zou de compiler niet weten hoe de klasse moet worden gegenereerd. Foo<int> f(0)werkt omdat Foo<int>de klasse genereert, waarbij Twordt vervangen door int. Door het type dat u de constructor aanroept, weet de compiler al dat de constructor een intaccepteert.


Antwoord 4, autoriteit 14%

De naam van de klas die je wilt instantiëren is
Foo<int>(zoals u aangeeft).

Het is ook mogelijk om Foo<short> f(0), of Foo<unsigned long> f(0),
of Foo<Foo<double>*> f(0). In die gevallen verwacht je echter niet dat de compiler het type kan raden als je alleen Foo f(0)schrijft.

Je zou je kunnen voorstellen dat een C++ zou kunnenzijn gespecificeerd met regels om te maken
sommige van dergelijke gissingen op bepaalde manieren (zoals de letterlijke 0impliceert typeparameter inten geen andere), maar dan zou de taal nog meer zijn
ingewikkelder dan het nu is en er zouden andere manieren zijn om
mensen om programmeerfouten te maken.
Eigenlijk schrijven wat je bedoelt in een verklaring als deze
lijkt niet te veel gevraagd.

Bewerken:nadat ik dit had gepost, merkte ik in een ander antwoord op dat er is
een voorstel om zo’n functie van C++ te maken, inderdaad zoals je je kunt voorstellen.

Other episodes