Problem mit Traits
-
Hey @ all,
ich beschäftige mich zur Zeit mit Templates in C++. Das ist mein Codetemplate <typename T> struct rgb{ T data[3]; static const int num_channels = 3; typedef T channel_value_type; rgb(){ data[0]=data[1]=data[2]=(T)0; } rgb(const T& v0, const T& v1, const T& v2){ data[0] = v0; data[1] = v1; data[2] = v2; } }; template <typename T> struct gray{ T intensity; gray(const T& v=0) : intensity(v){} }; template <typename C> struct calc{ int num_channels(const C& color){ return color.num_channels; } }; template <> struct calc<gray>{ int num_channels(const gray& color){ return 1; } };Mein Problem tritt nun bei der Templatespezialisierung auf. Der Compiler mault da nämlich folgendermaßen rum:
Fehler: Typ/Wert des Arguments 1 passt nicht in Template-Parameterliste für »template<class C> struct calc«
Fehler: einen Typ erwartet, »gray« erhaltenLeider seh ich den Fehler absolut nicht und wollte fragen, ob mir eventuell jemand weiter helfen kann.
Ich bedanke mich schon mal im Vorfeld für eure Antworten und verbleibe
Mit freundlichen Grüßen
-
Der erste Template-Parameter von calc ist ein ein vollständiger Typ.
grayist aber kein vollständiger Typ, sondern ein Klassentemplate. Du musst wenn schon gray spezialisiert angeben:template <> struct calc<gray<...>> // ...
-
Sone hat's schon gesagt ... übersetzen würde z.B.:
template <typename T> struct calc<gray<T> >{ int num_channels(const gray<T>& color){ return 1; } };
-
Ahh, danke! Das war wohl zu offensichtlich!

Ich habe allerdings noch eine Folgefrage.
Warum sagt der Compiler dann zu folgendem Code:template <typename COLOR, typename TYPE> struct channel{ TYPE get_channel(const COLOR& color, int i){ return color.data[i]; } }; template <typename TYPE> struct channel<gray<TYPE> >{ TYPE get_channel(const gray<TYPE>& color, int i){ return color.intensity; } };Fehler: für »template<class COLOR, class TYPE> struct channel« bereitgestellt
Fehler: falsche Anzahl der Templateargumente (1, sollte 2 sein)Was mach ich denn falsch?
Mit freundlichen Grüßen
-
DorJo schrieb:
Was mach ich denn falsch?
Du versuchst,
channel<gray<TYPE> >zu spezialisieren, aber die Klasse gibt es gar nicht!Aber
channel<gray<TYPE>,TYPE>gibt es:template <typename TYPE> struct channel<gray<TYPE>, TYPE>{ TYPE get_channel(const gray<TYPE>& color, int i){ return color.intensity; } };Falls dich das doppelte TYPE in der Nutzung stört, bleibt dir nichts anderes übrig als eine Helferfunktion zu schreiben
template <typename T> channel<gray<T>, T> make_channel(gray<T>)
-
Tatsächlich kompiliert es jetzt!
VIELEN VIELEN DANK!
Und wie würde ich die Methode get_channel() jetzt aufrufen (Also für einen Gray)? Irgendwie verwirrt mich das alles noch. Kennt jemand vielleicht ein gutes Tutorial?Mit freundlichen Grüßen
-
Kennt jemand vielleicht ein gutes Tutorial?
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
Kapitel 14 - Templates.

Spaß beiseite - hol dir ein gutes Grundlagenbuch.
Und wie würde ich die Methode get_channel() jetzt aufrufen (Also für einen Gray)?
Mit den entsprechenden Argumenten?
-
http://www.open-std.org/j ....... ocs/papers/2012/n3337.pdf
GEHT LOS!

#include "color.hpp" #include <iostream> int main(){ gray<int> *a = new gray<int>(); a->intensity = 10; std::cout<<channel<int>::get_channel(*a,2)<<std::endl; delete a; return 0; }Das geht nicht!
Aber wie geht es dann? 
-
Welchen Code hast du denn jetzt genommen? Den von orjod?
-
HAHA LOL! Sry, ja, das war ich. Hab mich beim Benutzernamen verschrieben! SORRYYY!!! Und ja, ich hab den Code genommen
-
Halt stop, jetzt hab ich mich doch glatt verguggt! Also das hab ich nicht geschrieben. Aber ich habe den Code von ojrod genommen! Ich glaub ich sollte mal einen Kaffee trinken gehen um ein wenig runter zu kommen!
-
Also ich habe es jetzt mit viel Hilfe und noch leichtem Unverständniss gelöst bekommen.
Falls es jemanden interessiert:template <template<typename> class COLOR> struct is_gray{ template<typename TYPE> static TYPE getValue(const COLOR<TYPE>& color, int i) { return color.data[i]; } }; template <> struct is_gray<gray>{ template<typename TYPE> static TYPE getValue(const gray<TYPE>& color, int i) { return color.intensity; } }; template <template<typename> class COLOR, typename TYPE> TYPE get_channel(const COLOR<TYPE>& color, int i){ return is_gray<COLOR>::getValue(color, i); }Das nutzt jetzt, wenn mich nicht alles täuscht auch Traits-Klassen!
Mit freundlichen Grüßen
DorJo
-
Ein paar Anmerkungen:
struct rgb{ T data[3]; static const int num_channels = 3; ... struct gray{ ...Warum hat
rgbein Membernum_channelsundgraynicht, wobei du nachtraeglich zwei Funktionen definierst, die genau diesen Umstand korrigieren. Einfachnum_channelsauch ingraydefinieren und 2 Funktionen/Strukturen gespart. Was spricht gegenconstexp?int main(){ gray<int> *a = new gray<int>(); a->intensity = 10; std::cout<<channel<int>::get_channel(*a,2)<<std::endl; delete a;newunddeletein diesem Fall sind einfach verpoent.gray<int>einfach instantiieren ohne Heap ... schon wieder Zeilen gespart.Beim Namen
is_grayerwarte ich eine Funktion/Struktur, die mir angibt, ob die Farbe grau ist, d.h. irgendwie mitboolverknueft ist.
-
wir dürfen an den structs nichts ändern, deswegen können wir in gray nicht einfach num_Channels hinzufügen...
-
Sone schrieb:
Der erste Template-Parameter von calc ist ein ein vollständiger Typ.
Das ist bloss ein Typ. Vollständig (complete) muss der - jedenfalls im gezeigten Code - nicht sein.
Wieso nicht einfach ein normales Funktionstemplate verwendet wird (statt Memberfunktion/-template), erschliesst sich mir nicht. So ist nur unnötig Redundanz drin.