2013-02-21 17 views
8

Czy istnieje idiom dla ścisłego typedef w C++, być może przy użyciu szablonów?Idiom dla ścisłego typedef w C++

Coś jak:

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; 

Więc mogę zrobić coś takiego błędu w czasie kompilacji:

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

x = y; // whoops 

__LINE__ tam wygląda to może być kłopot, ale bym nie preferują aby ręcznie utworzyć zestaw stałych, aby każdy typ był unikalny.

+1

Współrzędne nie są bardzo dobre zastosowanie w tej sprawie. Iloczyn dwóch współrzędnych nie jest współrzędną, itp. Zamiast tego możesz spojrzeć na Boost.Units. –

+2

Usunąłem moją odpowiedź, która zasugerowała [BOOST_STRONG_TYPEDEF] (http://www.boost.org/doc/libs/1_53_0/libs/serialization/doc/strong_typedef.html), ponieważ podobno działa to w celu uzyskania rozdzielczości przeciążenia, ale nie generuje kompilacji błędy w przydziale krzyżowym. – Angew

+0

Pytam o wartość tego, co chcesz zrobić. Co dzieje się, gdy na przykład chcesz wykonać rotację? 'x = sin (theta) * y + cos (theta) * x' powinno być w pełni poprawne. –

Odpowiedz

5

Używam czegoś podobnego w moim projekcie. Używam tylko tagowania typu zamiast int. Działa dobrze w mojej konkretnej aplikacji.

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; 

Zauważ, że TAG_ * klasy nie muszą być zdefiniowane w dowolnym miejscu, są one po prostu tagi

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

x = y; // error 
+0

Myślę, że wyglądałoby to ładniej z prostym "#define new_type (base, tag) typedef new_type <## base, class TAG _ ## tag> tag;" – slacy

+1

@slacy dunno, uważam, że makra są brzydkie i unikaj ich –

2

Nie. Istnieją propozycje, aby przejść do następnego standardu (C++ 14, a może C++ 17), ale nie w C++ 11.

+1

-1: Nie zapytał, czy jest w języku, i czy istnieją sposoby na zrobienie tego w "przestrzeni użytkownika" ". Dlatego ta odpowiedź jest niepoprawna. –

+0

Nie ma możliwości zrobienia tego w przestrzeni użytkownika, która jest taka sama, jak proponowana funkcja języka. – Puppy

+0

Co z tego jest takie samo, jak podano w pytaniu? Teraz, gdy odpowiedź Angew została unieważniona, jestem otwarty na taką możliwość, ale wymagam tu twojego wkładu. –

0

z 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()); 
} 

wyjściowe:

x1 
x2 
y1 
y2 
i1 
i2 

kompilatory:

Visual Studio 2015, GCC 4.8.x