[C++] min/max überladen (gelöst)

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Schrompf
Moderator
Beiträge: 4884
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

[C++] min/max überladen (gelöst)

Beitrag von Schrompf »

Hallo Leute,

ich habe mal wieder eine absurde Idee gehabt. Ich habe einen eigenen Typ struct Vektor3D { int x, y, z; } definiert. Und ich dachte mir, ich könnte ganz garstig per Template Specialization std::min() und max() überladen, so dass es elementweise mit meinem Typ arbeitet. Das sieht im Code so aus:

Code: Alles auswählen

namespace std
{
  template <>
  Vektor3D min( const Vektor3D& a, const Vektor3D& b) { return Vektor3D( min( a.x, b.x), min( a.y, b.y), min( a.z, b.z)); }
}
Sollte nach meinem Verständnis eine Spezialisierung der Template-Funktion für den Typ Vektor3D werden. Ist es aber nicht. VS2010 meint, es kenne "min" nicht. Was ist hier faul?

Edit1: Eigentrottel, erster Akt: Vektor3D lag in einem anderen namespace, aber die Spezialisierung muss ich ja im std::namespace definieren. Expliziter Namespace vor jedem Typnamen und jetzt lautet die Fehlermeldung: "template-Argument für const _ty& konnte nicht von Logik::Vektor3D hergeleitet werden". Gibt es eine Methode, den Typ sauber zu spezifizieren?

Edit2: Ich glaube, std::min liefert eine const reference zurück, während ich ja ein neues Objekt zurückgebe. Aber das müsste nach meinem Verständnis egal sein, dass bei der Funktionsüberladung der Rückgabewert ja nicht zur Funktionssignatur gehört und ich den demzufolge ändern können müsste.

Edit3: sorry, manchmal bin ich etwas voreilig beim Beten zu den C++-Gottheiten. Das Problem ist ganz simpel zu lösen, indem ich einfach auf jeden template-Kram verzichte und die Funktionen als einfache Überladungen stehen lasse. So sieht das dann aus:

Code: Alles auswählen

namespace std
{
  Vektor3D min( const Vektor3D& a, const Vektor3D& b) { return Vektor3D( min( a.x, b.x), min( a.y, b.y), min( a.z, b.z)); }
}
ohne template <> und fertig. Tut mir leid, dass ich 30s eurer Lebenszeit für das Lesen dieses Beitrags verschwendet habe.
Zuletzt geändert von Schrompf am 26.07.2012, 17:53, insgesamt 1-mal geändert.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Artificial Mind
Establishment
Beiträge: 802
Registriert: 17.12.2007, 17:51
Wohnort: Aachen

Re: [C++] min/max überladen

Beitrag von Artificial Mind »

Sind nicht alle Definitionen, die man selber in "namespace std" ablegt, per Definition undefined behaviour?
Benutzeravatar
Schrompf
Moderator
Beiträge: 4884
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [C++] min/max überladen (gelöst)

Beitrag von Schrompf »

Oha, eine Antwort, während ich noch im Edit mit mir selbst geredet habe. Kann sein, dass das unspezifiziertes Verhalten ist. [edit: und es ist definitiv nicht schön, das stimmt.] Aber das ist mir ehrlich gesagt schnuppe.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] min/max überladen (gelöst)

Beitrag von dot »

Ja, spezialisieren wäre ok, aber überladen ist laut C++ Standard verboten.

Was genau ist denn das Problem mit

Code: Alles auswählen

namespace std
{
  template <>
  inline Vektor3D min<Vektor3D>(const Vektor3D& a, const Vektor3D& b)
  {
    return Vektor3D(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
  }
}
Benutzeravatar
Schrompf
Moderator
Beiträge: 4884
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [C++] min/max überladen (gelöst)

Beitrag von Schrompf »

Ah, stimmt. Das ist die Syntax zur expliziten Angabe des Template-Typs. Danke, dot!

[edit] Nein, doch nicht. Der Compiler meckert dann (zu Recht), dass die Funktionsspezialisierung im Rückgabetyp vom Orginal abweicht. std::min() liefert ursprünglich einen const Type& zurück, während ich ja zwangsweise per Value zurückgebe. Dann doch nicht.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [C++] min/max überladen (gelöst)

Beitrag von BeRsErKeR »

dot hat geschrieben:

Code: Alles auswählen

namespace std
{
  template <>
  inline Vektor3D min<Vektor3D>(const Vektor3D& a, const Vektor3D& b)
  {
    return Vektor3D(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
  }
}
Das wäre meiner Meinung nach auch nicht im Sinne der Definition von "min", welches das Minimum von zwei Objekten (in diesem Fall Vektoren) liefert. In deinem Fall liefert es den Vektor, der die Minimal x-/y-/z-Werte beider Vektoren liefert, aber nicht den jenigen Vektor der nach einem globalen Kriterium "kleiner" ist. Daher finde ich sowohl deinen Ansatz als auch das allgemeine Vorhaben für unsinnig, es sei denn man geht vom minimalen Wert des Betrags des Vektors aus, was wiederum in meinen Augen einen Sinn machen würde, aber nicht unbedingt eindeutig ist.
Ohne Input kein Output.
Benutzeravatar
spobat
Beiträge: 86
Registriert: 13.09.2010, 00:20
Kontaktdaten:

Re: [C++] min/max überladen (gelöst)

Beitrag von spobat »

Ich weiss nicht, ob "min" dafuer der richtige Ansatz ist. Schliesslich geht man bei "min" davon aus, dass einer der beiden Parameter zurueckgegeben wird.
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: [C++] min/max überladen (gelöst)

Beitrag von Aramis »

Ja, es ist sogar definitiv der falsche / unspezifizierte Ansatz.

Davon abgesehen ist es wirklich nuetzlich – wir haben genau diesen Code uebrigens in Assimp drin:

Code: Alles auswählen

namespace std {

	// std::min for aiVector3D
	template <typename TReal>
	inline ::aiVector3t<TReal> min (const ::aiVector3t<TReal>& a, const ::aiVector3t<TReal>& b)	{
		return ::aiVector3t<TReal> (min(a.x,b.x),min(a.y,b.y),min(a.z,b.z));
	}
}
Es handelt sich auch um eine Ueberladung, keine partielle Spezialisierung (die nach min nochmal spitze Klammern haette).

Man sollte die Dinger mal umbenennen (ich brauchte ja nur ein min weil sich damit einige Algorithmen die sowohl auf floats, Vektoren und ints arbeiten leicht formulieren liessen - korrekt waere es, einen anderen Namen zu verwenden und per default intern std::min aufzurufen).

Ich werde das nicht machen, du auch nicht :-)
Benutzeravatar
Schrompf
Moderator
Beiträge: 4884
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [C++] min/max überladen (gelöst)

Beitrag von Schrompf »

Naja... ich habe das jetzt in eine freie Funktion ausgelagert, weil die elementweise Arbeitsweise halt doch nicht der ursprünglichen Bedeutung von min() entspricht. Außerdem hat man die Funktion so schön nah bei der ursprünglichen Klasse und findet sie auch, wenn man mal schnell nachschauen geht, welche Operationen der Datentyp nun unterstützt.

Code: Alles auswählen

struct Vektor3D
{
  ....

  inline static Vektor3D min(const Vektor3D& a, const Vektor3D& b) { return ...; }
}
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] min/max überladen (gelöst)

Beitrag von dot »

Ja, so hätt ich's von vornherein gemacht, ich dachte nur, dass du aus irgendeinem Grund dein min() unbedingt im namespace std haben musst. Wobei ich keine statische Memberfunktion, sondern einfach eine freie Funktion machen würd:

Code: Alles auswählen

struct Vector3D
{
};

inline Vector3D min(const Vector3D& a, const Vector3D& b)
{
  return ...;
}
Benutzeravatar
Schrompf
Moderator
Beiträge: 4884
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [C++] min/max überladen (gelöst)

Beitrag von Schrompf »

Nein, dazu gibt es bei mir zuviele kleine lokale Variablen, die min oder max heißen. Ich finde, freie Operatoren und Funktionen sind schwer zu finden... ich mag es lieber, wenn jede Funktion einen Scope hat, so dass man sie thematisch zuordnen und auch wiederfinden kann, wenn man grade beim Blättern durch den Sourcecode ist.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: [C++] min/max überladen (gelöst)

Beitrag von dot »

Gut, ich bin eben ein Fan von freien Funktionen und ADL. ;)
Nachteil deiner Lösung ist, dass sie nicht ganz so generisch und im Zusammenhang mit templates daher potentiell etwas problematisch ist...
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [C++] min/max überladen (gelöst)

Beitrag von BeRsErKeR »

Schrompf hat geschrieben:... ich mag es lieber, wenn jede Funktion einen Scope hat, so dass man sie thematisch zuordnen und auch wiederfinden kann, wenn man grade beim Blättern durch den Sourcecode ist.
WIe wärs mit einem Namensraum?
Ohne Input kein Output.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4884
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [C++] min/max überladen (gelöst)

Beitrag von Schrompf »

Kann man auch machen. Dem Compiler ist das wurscht. Hier habe ich halt bereits eine Klasse da, die thematisch exakt den Scope der freien Funktion darstellt, also kann ich die Funktion da auch als static reinpacken.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [C++] min/max überladen (gelöst)

Beitrag von BeRsErKeR »

Schrompf hat geschrieben:Kann man auch machen. Dem Compiler ist das wurscht. Hier habe ich halt bereits eine Klasse da, die thematisch exakt den Scope der freien Funktion darstellt, also kann ich die Funktion da auch als static reinpacken.
Naja du hast in einer statischen Memberfunktion aber Zugriff auf private Teile der Klasse, was nicht nur unnötig ist, sondern auch die Kapselung reduziert. Da ich aber weiß, dass dir das bewusst ist, reit ich nicht weiter drauf rum. Ich kann dich irgendwo nachvollziehen. ;) Besser ist halt immer ein Namensraum, aber nicht immer hübscher für den Programmierer.
Ohne Input kein Output.
Antworten