Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   
Forentreff 2012     
Bücher-Shop mit Amazon (Buchkategorien)C++ : Referenzen zu C++ : C++ Builder : Visual C++ : C# : Java : Spieleprogrammierung : Systemprogrammierung Linux : Software-Entwicklung : .NET : Compilertechnik : Algorithmen & Datenstrukturen : Objektorientierung : Entwurfsmuster : UML : eXtreme Programming : Scrum : Projektmanagement : Software-Testing : Datenbanken : Tom DeMarco : Dilbert : User Friendly
C/C++ Forum :: C++ (auch C++0x und C++11) ::  Template-Methode mit Default-Parameter  
Gehen Sie zu Seite Zurück  1, 2, 3
  Zeige alle Beiträge auf einer Seite
Auf Beitrag antworten
Autor Nachricht
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 13529
Beitrag hustbaer Mitglied 02:49:33 12.02.2011   Titel:              Zitieren

Der Bug tritt mit freien Funktionen genau so auf:

C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = NumericType());

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
    NumericType dummy = step;
    std::cout << value << ", " << step << std::endl;
}

int main()
{
    foobar(2);
    foobar(3.14);
    return 0;
}

// output:
// 2, 0
// 4.27698e+086, 1.16762e-307
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = NumericType());

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
NumericType dummy = step;
std::cout << value << ", " << step << std::endl;
}

int main()
{
foobar(2);
foobar(3.14);
return 0;
}

// output:
// 2, 0
// 4.27698e+086, 1.16762e-307
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = NumericType());

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
    NumericType dummy = step;
    std::cout << value << ", " << step << std::endl;
}

int main()
{
    foobar(2);
    foobar(3.14);
    return 0;
}

// output:
// 2, 0
// 4.27698e+086, 1.16762e-307


Scheint aber wirklich davon abhängig zu sein dass Deklaration und Definition getrennt sind. Und ich kann's auch nicht mit etwas anderem als double reproduzieren. Und das auch nur, wenn vorher oder nachher ein Aufruf mit etwas anderem als double erfolgt.

Auch nicht uninteressant folgendes:
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = 2); // <- hier direkt 2 statt NumericType() (0 oder andere Integer gehen genau so)

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
    NumericType dummy = step;
    std::cout << value << ", " << step << std::endl;
}

int main()
{
    foobar(2);
    foobar(3.14);
    return 0;
}

// output:
// 2, 2
// 4.27698e+086, 3.75217e-308
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = 2); // <- hier direkt 2 statt NumericType() (0 oder andere Integer gehen genau so)

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
NumericType dummy = step;
std::cout << value << ", " << step << std::endl;
}

int main()
{
foobar(2);
foobar(3.14);
return 0;
}

// output:
// 2, 2
// 4.27698e+086, 3.75217e-308
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = 2); // <- hier direkt 2 statt NumericType() (0 oder andere Integer gehen genau so)

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
    NumericType dummy = step;
    std::cout << value << ", " << step << std::endl;
}

int main()
{
    foobar(2);
    foobar(3.14);
    return 0;
}

// output:
// 2, 2
// 4.27698e+086, 3.75217e-308

Immer noch (fast) der selbe falsche Output.

Wenn man als Default-Wert allerdings ein double Literal hinschreibt...
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = 2.71828); // <- jetzt mit double literal hier

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
    NumericType dummy = step;
    std::cout << value << ", " << step << std::endl;
}

int main()
{
    foobar(2);
    foobar(3.14);
    return 0;
}

// output:
// 2, 1949120276
// 3.14, 2.71828
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = 2.71828); // <- jetzt mit double literal hier

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
NumericType dummy = step;
std::cout << value << ", " << step << std::endl;
}

int main()
{
foobar(2);
foobar(3.14);
return 0;
}

// output:
// 2, 1949120276
// 3.14, 2.71828
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename NumericType>
void foobar(NumericType value, NumericType step = 2.71828); // <- jetzt mit double literal hier

template<typename NumericType>
void foobar(NumericType value, NumericType step)
{
    NumericType dummy = step;
    std::cout << value << ", " << step << std::endl;
}

int main()
{
    foobar(2);
    foobar(3.14);
    return 0;
}

// output:
// 2, 1949120276
// 3.14, 2.71828

Auch falsch, aber ganz anders falsch :)

_________________
"Let there be Licht..." http://lichttools.sourceforge.net/
Sehr cooles ASCII Spiel (leider nicht von mir): ASCII-Scramble - http://www.roskakori.at/ascii/
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 13529
Beitrag hustbaer Mitglied 03:51:44 12.02.2011   Titel:              Zitieren

Der 64 Bit Compiler scheint übrigens genau so betroffen zu sein.

_________________
"Let there be Licht..." http://lichttools.sourceforge.net/
Sehr cooles ASCII Spiel (leider nicht von mir): ASCII-Scramble - http://www.roskakori.at/ascii/
drakon
Mitglied

Benutzerprofil
Anmeldungsdatum: 28.01.2008
Beiträge: 6824
Beitrag drakon Mitglied 12:52:06 12.02.2011   Titel:              Zitieren

hustbaer schrieb:
Der Bug tritt mit freien Funktionen genau so auf:

Ah. Ich habe das nur mit direkt definierten freien Funktionen probiert.

Zitat:
Der 64 Bit Compiler scheint übrigens genau so betroffen zu sein

Assembler Code:
    f.bar(2);
000000013F39165B  xorpd       xmm2,xmm2  
000000013F39165F  mov         edx,2  
Assembler Code:
f.bar(2);
000000013F39165B xorpd xmm2,xmm2
000000013F39165F mov edx,2
Assembler Code:
    f.bar(2);
000000013F39165B  xorpd       xmm2,xmm2  
000000013F39165F  mov         edx,2  

Uh, oh. Ja.. sieht so aus.. ^^
Aber es gibt keinen Laufzeitfehler bei mir.

Scheint wirklich hauptsächlich an der Trennung zu liegen. Zum Glück implementieren die meisten templates direkt. :P

_________________
Blog: www.drakon.ch
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 13529
Beitrag hustbaer Mitglied 00:57:35 13.02.2011   Titel:              Zitieren

Tjaaah... die meisten.

In einem grösseren Projekt das ich gerade entwickle (mit VC 2005) hab' ich *einige* Templates mit getrennter Deklaration und Definition. Zwecks übersichtlichkeit der Header Files (Definition steht in eigenen .inl Files).
Und auch mit Default-Parametern und die Variablen sind auch oft vom Typ double :(

EDIT:
Wobei... dort werden eigentlich nur doubles verwendet, und nie was anderes. Sollte dann OK sein. Hab auch noch keinen derartigen Fehler beobachtet. Doof ist es trotzdem. /EDIT

_________________
"Let there be Licht..." http://lichttools.sourceforge.net/
Sehr cooles ASCII Spiel (leider nicht von mir): ASCII-Scramble - http://www.roskakori.at/ascii/


Zuletzt bearbeitet von hustbaer am 01:01:13 13.02.2011, insgesamt 1-mal bearbeitet
DJohn
Mitglied

Benutzerprofil
Anmeldungsdatum: 17.06.2003
Beiträge: 105
Beitrag DJohn Mitglied 10:33:08 13.02.2011   Titel:              Zitieren

@hustbaer

Beim Versuch ein Minimalbeispiel zu erstellen, konnte ich den Fehler bei freien Funktionen auch nicht reproduzieren. Hatte da wahrscheinlich wie drakon noch eine der anderen Bedingungen wegreduziert. Bei Deiner zweiten Variante (Default-Wert ist ein int) reicht es aus, nur eine Template-Instanz mit double zu erzeugen um zumindest bei VS2005 den Fehler zu provozieren. Die zusätzliche Bedingung, dass man mindestens 2 Template-Instanzen mit unterschiedlichen Typen für den Fehler braucht, fällt dann weg.

Ich hatte auch nur wegen der Übersichtlichkeit Deklaration und Definition getrennt, kein großes Problem, dass jetzt zu ändern. Aber wenn so ein Fehler erstmal auftritt, ist man natürlich unsicher, unter welchen Bedingungnen noch dieses undefinierte Verhalten auftreten kann.
Deshalb, nochmal Danke an alle die sich an der Diskussion beteiligt haben, ich denke, wir haben jetzt ganz gut eingegrenzt, wann der Fehler auftritt.

djohn
hustbaer
Mitglied

Benutzerprofil
Anmeldungsdatum: 27.10.2006
Beiträge: 13529
Beitrag hustbaer Mitglied 11:38:20 13.02.2011   Titel:              Zitieren

Noch was lustiges...
Folgendes compiliert mit VS 2010:
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

int g_i = 42;

template<typename T>
void baz(T a1, T* a2 = &g_i); // <- default argument should only work for T = int

template<typename T>
void baz(T a1, T* a2)
{
    std::cout << a1 << ", " << *a2 << std::endl;
}

class c {};

std::ostream& operator << (std::ostream& os, c const&)
{
    return os;
}

int main()
{
    baz(2);
    baz(3.14);   // compiles OK, but should not
    baz("test"); // compiles OK, but should not
    baz(c());    // compiles OK, but should not
    return 0;
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

int g_i = 42;

template<typename T>
void baz(T a1, T* a2 = &g_i); // <- default argument should only work for T = int

template<typename T>
void baz(T a1, T* a2)
{
std::cout << a1 << ", " << *a2 << std::endl;
}

class c {};

std::ostream& operator << (std::ostream& os, c const&)
{
return os;
}

int main()
{
baz(2);
baz(3.14); // compiles OK, but should not
baz("test"); // compiles OK, but should not
baz(c()); // compiles OK, but should not
return 0;
}
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>

int g_i = 42;

template<typename T>
void baz(T a1, T* a2 = &g_i); // <- default argument should only work for T = int

template<typename T>
void baz(T a1, T* a2)
{
    std::cout << a1 << ", " << *a2 << std::endl;
}

class c {};

std::ostream& operator << (std::ostream& os, c const&)
{
    return os;
}

int main()
{
    baz(2);
    baz(3.14);   // compiles OK, but should not
    baz("test"); // compiles OK, but should not
    baz(c());    // compiles OK, but should not
    return 0;
}

Beim Ausführen kommt natürlich nur Mist raus...

:eek: :eek: :eek:

_________________
"Let there be Licht..." http://lichttools.sourceforge.net/
Sehr cooles ASCII Spiel (leider nicht von mir): ASCII-Scramble - http://www.roskakori.at/ascii/


Zuletzt bearbeitet von hustbaer am 11:39:36 13.02.2011, insgesamt 1-mal bearbeitet
C/C++ Forum :: C++ (auch C++0x und C++11) ::  Template-Methode mit Default-Parameter  
Gehen Sie zu Seite Zurück  1, 2, 3
Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info, www.c-sar.de, www.c-plusplus.net und www.baeckmann.de enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.