21 Stimmen

Deklarieren von Typen ohne implizite Konvertierung in C++

Ich möchte meine eigenen numerischen Typen deklarieren, genau wie unsigned int, aber ich möchte nicht, dass die Typen implizit konvertiert werden. Dies habe ich zuerst versucht: typedef unsigned int firstID; typedef unsigned int secondID;

aber dies ist nicht gut, da die beiden Typen sind nur Synonyme für unsigned int, so sind frei austauschbar.

Ich möchte, dass dies einen Fehler verursacht:

firstID fid = 0;
secondID sid = fid; // no implicit conversion error

aber das hier ist in Ordnung:

firstID fid = 0;
secondID sid = static_cast<secondID>(fid); // no error

Mein Grund ist, dass Funktionsargumente stark typisiert sind, z. B.:

void f( firstID, secondID ); // instead of void f(unsigned int, unsigned int)

Was ist der Mechanismus, nach dem ich suche?

Gracias

Si

1 Stimmen

Es gibt keine Möglichkeit, dies zu tun, außer man macht die Typen zu tatsächlichen Klassen oder Strukturen.

0 Stimmen

Wurde diese Frage nicht bereits gestellt? stackoverflow.com/questions/376452/

8voto

Alexander Poluektov Punkte 7470

Vielleicht BOOST_STRONG_TYPEDEF-Form boost/strong_typedef.hpp helfen würde.

0 Stimmen

Es macht Sinn, dass Boost diese Möglichkeit hat. Es ist keine Raketenwissenschaft, aber es ist eine Menge Arbeit, alle Betreiber zu bekommen, und es schreit nach einer Vorlage.

0 Stimmen

Ich liebe Boost. Hat immer eine Antwort

4voto

Martin York Punkte 245363

Wie Sie festgestellt haben: typedef ist schlecht benannt (es sollte typealias sein (D hat ausdrücklich typealias hinzugefügt (das letzte Mal, als ich nachgesehen habe))

Die einzige Möglichkeit, dies zu tun, besteht also darin, zwei eindeutige Klassen zu erstellen.
Ich werde nicht sagen, dass Sie nicht eine Spezialisierung von static_cast<> schreiben können, um zu tun, was Sie wollen, aber ich denke (und ich habe nicht, dass viel Gedanken in es noch) tun so wäre eine schlechte Idee (auch wenn es legal), ich denke, ein besserer Ansatz ist zu haben jede Klasse Konstruktor verwenden unsigned int, die explizit sind (so gibt es keine automatische Konvertierung).

 struct FID
 {
     explicit FID(unsigned int v): value(v) {}
     operator unsigned int() {return value;}
     unsigned int value;
 };

 class SID {/* Stuff */};

 FID   fid(1U);
 SID   sid(2U);

 doSomthingWithTwoSID(sid,SID(static_cast<unsigned int>(fid));

Den Konstruktor explizit zu machen bedeutet, dass es keine automatische Konvertierung zwischen Typen gibt.
Durch das Hinzufügen des eingebauten Cast-Operators zu unsigned int kann dieser überall dort verwendet werden, wo ein int erwartet wird.

2voto

Matteo Italia Punkte 119470

Sie müssen Ihre eigenen Klassen für sie schreiben und alle benötigten Operatoren neu implementieren.

0 Stimmen

Autsch, ich hatte erwartet, dass es einfach sein würde! Schade, dass man nicht von einem unsigned int erben kann!

2 Stimmen

Sie können die Klasse jedoch als Vorlage schreiben, so dass sie zumindest mit allen primitiven Typen funktioniert.

1voto

T.E.D. Punkte 42630

Ahhh, ein Mitreisender von Ada, wie ich sehe.

Die einzige Möglichkeit, dies in C++ zu tun, besteht darin, Klassen zu deklarieren. Etwa so:

class first_100 {
public:
    explicit first_100(int source) {
        if (source < 1 || source > 100) {
           throw range_error;
        }
        value = source;
    };
    // (redefine *all* the int operators here)
private:
    int value;
};

Sie sollten sicherstellen, dass Sie Ihren int-Konstruktor definieren explicit so dass C++ es nicht verwendet, um implizit zwischen Ihren Typen zu konvertieren. Auf diese Weise wird dies nicht funktionieren:

first_100 centum = first_100(55);
int i = centum;

aber so etwas wie das hier könnte es sein (vorausgesetzt, Sie definieren es):

int i = centum.to_int();

1voto

agsamek Punkte 8114
struct FirstID { int id; };

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X