Hallo,
ich habe immer wieder den Fall, dass ich an member Funktionen eine
Klassenkonstante übergeben möchte um das erwünschte Verhalten zu
signalisieren.
Ich mache das so:
1
public:
2
using DeviceDirection = int;
3
const DeviceDirection InputDevice = 0;
4
const DeviceDirection OutputDevice = 1;
das ist eigentlich ganz nett und da nur ich selbst das api benutze,
stört der Nachteil eigentlich auch nicht: Was mich stört ist, dass man
einer Memberfunktion, zum Beispiel:
als Konstante (DeviceDirection) jetzt auch einfach einen beliebigen int
übergeben kann.
Das ist meine Frage. Geht es, und wenn ja, wie, dass ich die Sache so
gestalten kann, dass ich nur genau die vorgesehenen Konstanten übergeben
kann und nicht irgendwas konvertierbares?
Mit "nicht kann" meine ich so beiläufig oder aus Versehen, wie in dem
Beispiel oben, wo ich einfach ->enableDevice(12, 42) schreiben kann
statt die vorgesehen Konstanten zu verwenden. Ob man das mit Heimtücke
und Aufwand austricksen kann ist egal, sowas meine ich nicht.
vlg
Timm
Timm R. schrieb:> ...>> Das ist meine Frage. Geht es, und wenn ja, wie, dass ich die Sache so> gestalten kann, dass ich nur genau die vorgesehenen Konstanten übergeben> kann und nicht irgendwas konvertierbares?>> Mit "nicht kann" meine ich so beiläufig oder aus Versehen, wie in dem> Beispiel oben, wo ich einfach ->enableDevice(12, 42) schreiben kann> statt die vorgesehen Konstanten zu verwenden. Ob man das mit Heimtücke> und Aufwand austricksen kann ist egal, sowas meine ich nicht.>> vlg> Timm
Das was du suchst nennt sich strong type. Einen Einstieg ins Thema gibts
z.B. hier
https://www.fluentcpp.com/2016/12/08/strong-types-for-strong-interfaces/
Carl D. schrieb:> enum
Ja, das ist exakt für sowas gemacht.
Timm R. schrieb:> Ob man das mit Heimtücke und Aufwand austricksen kann ist egal, sowas> meine ich nicht.
Das freut mich zu hören, denn viele übertreiben es maßlos, indem sie
versuchen, ihre API gegen gezielte Sabotage abzusichern statt nur gegen
versehentliche Falschbenutzung.
Rolf M. schrieb:> Carl D. schrieb:>> enum>> Ja, das ist exakt für sowas gemacht.
Ergänzung einer Ungenauigkeit:
In diesem Fall möchte er TO explizit eine starke Typisierung.
Mit dem von dir zitiertem Ausschnitt könnte man denken, dass ein "enum"
genügen würde.
Ein einfacher enum (unscoped enum) hat implizite Konvertierungen
von/nach int. Im ursprünglichen Beitrag von Carl D. stand aber "enum
class", also ein scoped enum. Diese haben keine impliziten
Konvertierungen mit int und können nur über den Namen (oder explizite
Konvertierungen) verwendet werden.
Und das ist, was der TO verwenden möchte.
https://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations
Ralf C. schrieb:> Rolf M. schrieb:>> Carl D. schrieb:>>> enum>>>> Ja, das ist exakt für sowas gemacht.>> Ergänzung einer Ungenauigkeit:>> In diesem Fall möchte er TO explizit eine starke Typisierung.> Mit dem von dir zitiertem Ausschnitt könnte man denken, dass ein "enum"> genügen würde.> Ein einfacher enum (unscoped enum) hat implizite Konvertierungen> von/nach int.
Das ist falsch!
Beim Versuch, folgendes C++-Programm zu übersetzen:
1
enumDeviceDirection
2
{
3
InputDevice=0,
4
OutputDevice=1
5
};
6
7
voidenableDevice(intindex,DeviceDirectiondir)
8
{
9
}
10
11
intmain()
12
{
13
enableDevice(12,42);
14
}
meldet der Compiler:
1
enum.cpp: In function ‘int main()’:
2
enum.cpp:13:24: error: invalid conversion from ‘int’ to ‘DeviceDirection’ [-fpermissive]
3
enableDevice(12, 42);
4
^
5
enum.cpp:7:6: note: initializing argument 2 of ‘void enableDevice(int, DeviceDirection)’
6
void enableDevice(int index, DeviceDirection dir)
7
^~~~~~~~~~~~
Das ist exakt das, was der TO beschrieben hat, was passieren soll.
> Im ursprünglichen Beitrag von Carl D. stand aber "enum> class", also ein scoped enum. Diese haben keine impliziten> Konvertierungen mit int
Einen klassischen enum kann man nur nach int konvertieren, nicht von
int.
Rolf M. schrieb:> Einen klassischen enum kann man nur nach int konvertieren, nicht von> int.
Gut.
Der TO sei darauf hingewiesen, dass er sich aussuchen kann ob implizite
Konvertierungen von enum nach int zulässig sein sollen (unscoped enum),
oder nicht (scoped enum):
1
enumFoo{A=0,};
2
enumclassBar{B=0,};
3
4
voidfun()
5
{
6
Foo::A+42;// ok
7
Bar::B+42;// error: no match for ‘operator+’ (operand types are ‘Bar’ and ‘int’)
Hallo,
ich erinnere mich. Von enums hatte ich mich für mich persönlich
verabschiedet, weil mir überhaupt nicht gefiel, dass die Bezeichner aus
dem enum in den umgebenden Scope durchsickern.
Das hat natürlich den Vorteil das die Bezeichner für die Konstanten
eleganter sind.
Der scoped enum gefiel mir früher (TM) nicht, weil mir die Bezeichner
dadurch zu gesprächig waren, aber ich muss sagen, heute gefällt mir das
eigentlich sogar:
1
MidiManager::DeviceDirection::Input
Sieht doch eigentlich ganz nett aus. Ich werde also den enum class
verwenden.
Danke noch mal
vlg
Timm
Timm R. schrieb:> ich erinnere mich. Von enums hatte ich mich für mich persönlich> verabschiedet, weil mir überhaupt nicht gefiel, dass die Bezeichner aus> dem enum in den umgebenden Scope durchsickern.> Der scoped enum gefiel mir früher (TM) nicht, weil mir die Bezeichner> dadurch zu gesprächig waren, aber ich muss sagen, heute gefällt mir das> eigentlich sogar
Ja, das ist zu einem gewissen Grad auch Geschmackssache. Ich bin ja auch
nicht generell gegen enum class. Ich mag nur so lange Bandwurmnamen
nicht so arg - finde sie schwerer zu erfassen, und der zusätzliche
Bestandteil DeviceDirection:: gibt mit keine Information, die ich ohne
ihn nicht hätte.
Hallo Rolf,
Rolf M. schrieb:> finde sie schwerer zu erfassen,
ja das stimmt. Vielleicht stören sie mich heute deswegen nicht mehr so?
Damals (TM) war ich einfach krasser drauf. Lange Sessions und Hauptsache
die Tasten klappern :-)
Ich habe aber auch den Fluch, dass ich echt viel hin- und herschalten
muss zwischen verschiedenen Sprachen, vielen macht das nichts, mir
schon. Ich komme total schnell wieder raus und verwechsle Idiome etc.
Da können lange und selbsterklärende Namen schonmal eine echte Hilfe
sein :-)
> und der zusätzliche> Bestandteil DeviceDirection:: gibt mit keine Information, die ich ohne> ihn nicht hätte.
Aber geiler Punkt! Danke! Ich denke ich werde das Direction rausnehmen!
Das ist wirklich über. Das Device hilft mir aber.
vlg
Timm