2013-02-21 3 views
8

Esiste un idioma per un typedef rigoroso in C++, possibilmente utilizzando i modelli?Idiom per typedef rigoroso in C++

Qualcosa di simile:

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; 

modo che io possa fare una cosa del genere un errore di compilazione:

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

x = y; // whoops 

Il __LINE__ in là sembra che potrebbe essere problemi, ma non preferirei dover creare manualmente un insieme di costanti per mantenere unico ogni tipo.

+1

coordinate non sono un ottimo software per questo. Un prodotto di due coordinate non è una coordinata, ecc. Puoi invece guardare a Boost.Units. –

+2

Ho eliminato la mia risposta che suggeriva [BOOST_STRONG_TYPEDEF] (http://www.boost.org/doc/libs/1_53_0/libs/serialization/doc/strong_typedef.html), perché a quanto pare funziona per la risoluzione di sovraccarico ma non genera la compilazione errori sull'assegnazione incrociata. – Angew

+0

Mi interrogo sul valore di ciò che si vuole fare. Cosa succede quando si desidera eseguire una rotazione, ad esempio? 'x = sin (theta) * y + cos (theta) * x' dovrebbe essere interamente valido. –

risposta

5

Sto usando qualcosa di simile nel mio progetto. Solo io uso il tipo di tagging invece di int. Funziona bene nella mia particolare applicazione.

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; 

Nota che TAG_ * classi non hanno bisogno di essere definito da nessuna parte, sono solo tag

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

x = y; // error 
+0

Penso che sarebbe più bello con un semplice "#define new_type (base, tag) typedef new_type <## base, classe TAG _ ## tag> tag;" – slacy

+1

@slacy dunno, trovo le macro brutte e li evito –

2

No. Ci sono proposte per andare nello standard successivo (C++ 14, o forse C++ 17), ma non in C++ 11.

+1

-1: non ha chiesto se è nella lingua, e ci sono _re_ modi per farlo nello "spazio utente" ". Pertanto, questa risposta non è corretta. –

+0

Non ci sono modi per farlo nello spazio utente che sono gli stessi della funzione di linguaggio proposta. – Puppy

+0

Che dire di quello sono gli stessi di quanto affermato nella domanda? Ora che la risposta di Angew è stata invalidata, sono aperto alla possibilità, ma richiedo il tuo contributo qui. –

0

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

uscita:

x1 
x2 
y1 
y2 
i1 
i2 

compilatori:

Visual Studio 2015, GCC 4.8.x