[C++] Template default argument deduction

Pagina: 1
Acties:

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Topicstarter
Ik ben wat met template classes en functies aan het spelen, en produceerde op een gegeven moment een stuk code waarvan VC.net 2003 me een flauwe error gaf. Niet dat ik 'm niet snap, maar ik had verwacht dat ie daar wel uit zou komen. Echter, toen ik vervolgens de code door Comeau draaide om te checken of die het wel snapte, kwam die met een volgens mij helemaal idiote error.

Het geisoleerde stukje code is:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <vector>

template <class t_DataType> bool StdPredicate(const t_DataType& p_Low, 
                                              const t_DataType& p_High);

template <class t_DataType, class t_Predicate> 
void MySort(const std::vector<t_DataType> &p_Vector, 
            t_Predicate p_Predicate = StdPredicate<t_DataType>);

int main()
{
std::vector<int>  l_Vector;
MySort(l_Vector);

return 0;
}

Wat ik bij deze code zou verwachten: in de MySort regel herkent ie dat het een vector<int> is, wat het t_DataType argument vastlegt. Dit lukt ook. Vervolgens kan ie daarmee de parameter van de template functie die als default gebruikt is vastleggen, waarmee impliciet het template argument t_Predicate ook bekend is indien er geen 2e parameter meegegeven wordt. Geen kip en ei problemen zou je zo zeggen. VC.net 7.1 roept echter:
code:
1
2
error C2783: 'void MySort(const std::vector<t_DataType> &,t_Predicate)' : 
     could not deduce template argument for 't_Predicate'

Niet lief ;( Ik vind dat ie er gewoon niet genoeg moeite voor doet :P

Maar als ik vervolgens de code door Comeau Online tryout draai flipt die helemaal:
code:
1
2
3
4
5
6
"ComeauTest.c", line 11: error: no instance of function template "MySort"
matches the argument list

The argument types that you used are: (std::vector<int, std::allocator<int>>)
  MySort(l_Vector);
  ^

En wie heeft daar ooit een std::allocator ingestopt? Niet ik 7(8)7

De vragen dus: Waarom komt Comeau met die allocator op de proppen? Waarom gaat ie zo vreemd op z'n bek als ie geen fatsoenlijke reden ervoor heeft? Hoort deze code volgens de C++ standaarden te werken? Zijn er alternatieven behalve een overload van MySort maken met 1 parameter?

[ Voor 7% gewijzigd door curry684 op 01-02-2004 01:21 . Reden: layout ]

Professionele website nodig?


  • Eelis
  • Registratie: Januari 2003
  • Laatst online: 21-02-2015
.

[ Voor 105% gewijzigd door Eelis op 18-02-2015 19:50 ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Topicstarter
Held _o_ dat je dat in hoofdstuk 14.8.2.4, paragraaf 17 weet te vinden ;)

Maar okee, dmv overloads met 1 parameter ben ik er ook wel uit, maar is er nog een fatsoenlijke reden om dit te weigeren? Want zoals je ziet zou het iig in mijn voorbeeld gewoon afleidbaar moeten kunnen zijn voor een slimme compiler (en in dat ISO-voorbeeld ook).

Professionele website nodig?


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Topicstarter
*trap*

Kan iemand uitleggen of beargumenteren waarom deze constructie niet zou mogen werken? :)

Professionele website nodig?


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:03
Hmz, wat ontbreekt er aan de reactie van Eelis (behalve commentaar bij de gequote tekst)? Blijkbaar mag, volgens de standaard, een compiler geen types afleiden uit de default arguments van template parameters. Op het moment dat je MySort instantieert met als eerste argument een vector<int>, dan staat op dat moment alleen je eerste template parameter (t_DataType) vast. Hij moet echter ook t_Predicate invullen en de standaard zegt blijkbaar dat 'ie dat niet mag doen op basis van het default argument, wat jij in je redenatie wel doet. Dan houdt 't op, want bij gebrek aan een tweede argument heeft 'ie geen gegevens over t_Predicate.

Probeer jij maar eens het volledige type af te leiden zonder gebruik te maken van de defaultwaarde van het tweede argument van je functie. Dat lukt je ook niet. ;)

Als je de default argument expliciet herhaalt, werkt het uiteraard wel, want dan mag de compiler het type van het tweede argument wel gebruiken:
C++:
1
MySort(l_Vector, StdPredicate<std::vector<int> >);

Natuurlijk moet je dan nog wel ergens StdPredicate<std::vector<int> > hebben gedefinieerd. (Jammer van die spaties die tussen de >'s moeten btw, dat is echt ranzig).

De vraag waarom de standaard deze afleiding verbied kan ik niet zo 1-2-3 beantwoorden. Misschien zijn er ingewikkeldere casussen te verzinnen waarbij het echt teveel gevraagd zou zijn om de compiler dit te laten oplossen, of waarin het onwenselijk is dat de compiler een bepaalde afleiding maakt. Misschien vonden ze het al ingewikkeld genoeg worden, dus wilden ze de grens wat eerder trekken dan strict noodzakelijk. Misschien dat MSalters daar meer over kwijt wil. :P

offtopic:
Btw, jullie zijn echt gek, dat jullie om 06:13 resp. 06:21 nog/alweer C++ zitten te coden! :o

[ Voor 39% gewijzigd door Soultaker op 02-02-2004 17:15 ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Topicstarter
Soultaker schreef op 02 februari 2004 @ 17:09:
Hmz, wat ontbreekt er aan de reactie van Eelis (behalve commentaar bij de gequote tekst)?
Uitleg en argumentatie :)

Ik geloof direct dat de ISO-standaard het voorschrijft, echter ik kan met de beste wil van de wereld niet voorstellen waarom: het moet voor de compiler eenvoudig af te leiden zijn wat het datatype van die default parameter is. En ik kan met de beste wil van de wereld zo snel geen voorbeeld bedenken waarin deze constructie niet helder zou zijn, en dan nog zou er in die gevallen een ambiguity-error gegeven kunnen worden.

Ik zie nu overigens net pas dat ik de errormelding van Comeau verkeerd had gelezen om kwart over 1 's nachts, maar nog steeds snap ik ook niet waarom zij net als VC++ met een volstrekt onbegrijpelijke foutmelding komen: Comeau negeert gewoon de default declaratie, en VC zegt dat ie het niet kan afleiden, wat impliceert dat ie het wel zou mogen.

=[edit]=

en toen had je getuige je edit al door dat het me hier vooral even om de theoretische discussie gaat :P ik heb de code al sinds zaterdagnacht half 2 perfect draaien met een overload voor 1 parameter, maar dat vind ik gewoon ranzig en obsolete :)

=[edit2]=

offtopic:
bij mij was het iig 'nog' :P

[ Voor 15% gewijzigd door curry684 op 02-02-2004 17:16 ]

Professionele website nodig?


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
curry684 schreef op 01 februari 2004 @ 01:15:
[nohtml]Maar als ik vervolgens de code door Comeau Online tryout draai flipt die helemaal:
code:
1
2
3
4
5
6
"ComeauTest.c", line 11: error: no instance of function template "MySort"
matches the argument list

The argument types that you used are: (std::vector<int, std::allocator<int>>)
  MySort(l_Vector);
  ^

En wie heeft daar ooit een std::allocator ingestopt? Niet ik 7(8)7
lezen, curry :) Die allocator staat tussen de < > van std::vector, en is simpelweg het tweede argument. En als je dat niet invult, dan krijg je dus de default. 'k Zou toch zeggen dat je iets van default argumenten afweet ;)

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
curry684 schreef op 02 februari 2004 @ 17:15:
[...]
Uitleg en argumentatie :)

Ik geloof direct dat de ISO-standaard het voorschrijft, echter ik kan met de beste wil van de wereld niet voorstellen waarom: het moet voor de compiler eenvoudig af te leiden zijn wat het datatype van die default parameter is. En ik kan met de beste wil van de wereld zo snel geen voorbeeld bedenken waarin deze constructie niet helder zou zijn, en dan nog zou er in die gevallen een ambiguity-error gegeven kunnen worden.
14 is zo al moeilijk genoeg, daar moet je niet nog eens extra functionaliteit aan willen toevoegen, zeker als de workaround triviaal is. Ik vermoed - de compilerbouwers in kewstie kennende - dat EDG problemen zag in een paar testcases, en dat ze geen zin hadden om de standaard op te houden terwijl er een workaround was. Ik vermoed dat er kronkels gevonden zijn zoals
code:
1
2
3
4
template< typename T>
char f( T t );
template <typename T, typename D >
char f( T* t, D d = sizeof( f(*t) );


Jouw geval is in vergelijking simpel, en je had daarvoor een uizodering op de regel kunnen maken, maar om zo'n uitzondering toe te staan? De compilerbouwers mogen het best als extensie implementeren, maar dat vonden ze blijkbaar ook niet zo leuk.

Ik dacht bovendien handig te zijn, en het type gewoon als default template parameter te schrijven:
code:
1
template <class t_DataType, class t_Predicate = bool(*)(t_DataType const&, t_DataType const&) >
maar dat vindt como ook niet leuk;
error: default template arguments are not allowed for function templates
omdat ze Issue 226 nog niet hebben geimplementeerd. Maar goed, daar hebben ze nog een paar jaar voor.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein

Pagina: 1