2013-02-21 12 views
8

Gibt es ein Idiom für eine strikte typedef in C++, möglicherweise mit Vorlagen?Idiom für strikt typedef in C++

Etwas wie:

template <class base_type, int N> struct new_type{ 
    base_type p; 
    explicit new_type(base_type i = base_type()) : p(i) {} 
}; 

typedef new_type<int, __LINE__> x_coordinate; 
typedef new_type<int, __LINE__> y_coordinate; 

Also habe ich so etwas wie dies eine Kompilierung Fehler machen kann:

x_coordinate x(5); 
y_coordinate y(6); 

x = y; // whoops 

Die __LINE__ in sieht es wie es Schwierigkeiten geben könnte, aber ich würde es vorziehen, nicht um eine Reihe von Konstanten manuell zu erstellen, nur um jeden Typ einzigartig zu halten.

+1

Koordinaten sind nicht eine sehr gute Anwendung für diese. Ein Produkt aus zwei Koordinaten ist keine Koordinate usw. Sie können stattdessen Boost.Units betrachten. –

+2

Ich habe meine Antwort gelöscht, die [BOOST_STRONG_TYPEDEF] (http://www.boost.org/doc/libs/1_53_0/libs/serialization/doc/strong_typedef.html) vorgeschlagen hat, weil das anscheinend für die Überladungsauflösung funktioniert, aber keine Kompilierung generiert Fehler bei der Querzuweisung. – Angew

+0

Ich frage den Wert von was Sie tun möchten. Was passiert, wenn Sie zum Beispiel eine Rotation durchführen wollen? 'x = sin (theta) * y + cos (theta) * x' sollte vollständig gültig sein. –

Antwort

5

Ich verwende etwas ähnliches in meinem Projekt. Nur ich benutze type tagging statt int. Funktioniert gut in meiner speziellen Anwendung.

template <class base_type, class tag> class new_type{  
    public: 
    explicit new_type(base_type i = base_type()) : p(i) {} 

    // 
    // All sorts of constructors and overloaded operators 
    // to make it behave like built-in type 
    // 

    private: 
    base_type p; 
}; 

typedef new_type<int, class TAG_x_coordinate> x_coordinate; 
typedef new_type<int, class TAG_y_coordinate> y_coordinate; 

Beachten Sie, dass TAG_ * Klassen müssen nicht überall definiert werden, sind sie gerade Umbauten

x_coordinate x (1); 
y_coordinate y (2); 

x = y; // error 
+0

Ich denke, das würde mit einem einfachen "#define new_type (base, tag) typedef new_type <## base, Klasse TAG _ ## tag> Tag;" – slacy

+1

@slacy dunno, ich finde Makros hässlich und vermeide sie –

2

Nein. Es gibt Vorschläge dafür, in den nächsten Standard (C++ 14 oder vielleicht C++ 17) zu gehen, aber nicht in C++ 11.

+1

-1: Er fragte nicht, ob es in der Sprache ist, und es gibt Möglichkeiten, es in "User Space" zu tun ". Daher ist diese Antwort falsch. –

+0

Es gibt keine Möglichkeiten, dies im Benutzerbereich zu tun, die mit der vorgeschlagenen Sprachfunktion identisch sind. – Puppy

+0

Was ist das gleiche wie das, was in der Frage angegeben ist? Nun, da Angews Antwort für ungültig erklärt wurde, bin ich offen für die Möglichkeit, aber brauche Ihre Eingabe hier. –

0

Mit C++ 11:

#include <stdio.h> 

struct dummy {}; 

struct NotMineType 
{ 
    NotMineType(dummy) {} 
}; 

template <int N> 
struct type_scope 
{ 
    struct MyOwnType 
    { 
    }; 

    struct ConvertedToMineType : NotMineType 
    { 
     template <typename ...Args> 
     ConvertedToMineType(Args... args) : NotMineType(args...) {}; 
    }; 

    enum myint : int {}; 
}; 

typedef type_scope<0>::MyOwnType x1; 
typedef type_scope<1>::MyOwnType x2; 

typedef type_scope<0>::ConvertedToMineType y1; 
typedef type_scope<1>::ConvertedToMineType y2; 

typedef type_scope<0>::myint i1; 
typedef type_scope<1>::myint i2; 

void foo(x1) { printf("x1\n"); } 
void foo(x2) { printf("x2\n"); } 
void foo(y1) { printf("y1\n"); } 
void foo(y2) { printf("y2\n"); } 
void foo(i1) { printf("i1\n"); } 
void foo(i2) { printf("i2\n"); } 

int main() 
{ 
    foo(x1()); 
    foo(x2()); 
    foo(y1(dummy())); 
    foo(y2(dummy())); 
    foo(i1()); 
    foo(i2()); 
} 

Ausgang:

x1 
x2 
y1 
y2 
i1 
i2 

Compiler:

Visual Studio 2015 GCC 4.8.x