2010-09-18 23 views
5

Tengo dos programas de C++ que necesitan tener un mapa type -> int que se conoce en tiempo de compilación e igual entre los dos programas. Además, me gustaría asegurarme automáticamente en tiempo de compilación de que el mapa es uno a uno. ¿Cómo resolverías eso? (C++ 0x-extensiones están permitidas). La primera parte es fácil: Comparte unescriba a la asignación int

template < typename T > struct map; 
template <> struct map <...> { enum { val = ...; }; }; 

entre los programas. (La segunda parte significa que no quiero definir accidentalmente el mismo val para dos tipos diferentes en algún lugar de mis programas.)

+0

¿Puedo preguntar para qué sirve este mapeo? – sellibitze

+0

posible duplicado de [Tipo de conversión de metaprograma de plantilla a número único] (http://stackoverflow.com/questions/1708458/template-metaprogram-converting-type-to-unique-number) – kennytm

+0

El mapa se usará para comunicar datos arbitrarios entre un emisor y un programa receptor (esa es también la razón por la cual esta pregunta no es duplicada; se trata de dos programas que necesitan compartir el mismo mapa). – Thomas

Respuesta

9

Una forma de asegurar las identificaciones uniqe es abusar función friend definiciones

template<int N> 
struct marker_id { 
    static int const value = N; 
}; 

template<typename T> 
struct marker_type { typedef T type; }; 

template<typename T, int N> 
struct register_id : marker_id<N>, marker_type<T> { 
private: 
    friend marker_type<T> marked_id(marker_id<N>) { 
    return marker_type<T>(); 
    } 
}; 

template<typename T> 
struct map; 

template<> 
struct map<int> : register_id<int, 0> { }; 

// The following results in the following GCC error 
// x.cpp: In instantiation of 'register_id<float, 0>': 
// x.cpp:26:43: instantiated from here 
// x.cpp:14:29: error: new declaration 'marker_type<float> marked_id(marker_id<0>)' 
// x.cpp:14:29: error: ambiguates old declaration 'marker_type<int> marked_id(marker_id<0>)' 
// 
//// template<> 
//// struct map<float> : register_id<float, 0> { }; 
+0

¡Genial! Esta parece ser la solución perfecta, ya que me libera de tener que especificar todos los tipos en una lista. – Thomas

+1

@Thomas ahora también muestra los tipos conflictivos en el mensaje de error. –

2

¿Qué le parece usar boost::mpl::map? Compartir algo como:

// Include your headers 

using namespace boost::mpl; 
typedef map< 
     pair<1,MyFirstClass> 
    , pair<2,MySecondClass> 
    , pair<3,MyThirdClass> 
    > m; 
1

Ellos no lo hacen estrictamente en tiempo de compilación, pero este par de funciones automáticamente generar un identificador único para cada tipo que se les pasa:

template<class T> 
int generate_type_id() { 

    static int value = 0; 
    return value++; 

} 

template<class T> 
int type_id() { 

    static int value = generate_type_id<T>(); 
    return value; 

} 

Y usted debe ser capaz de asegurar que la participación de dos aplicaciones t él mismos identificadores para un tipo dado de invocar explícitamente las funciones con el fin de ambos proyectos:

type_id<int>(); 
type_id<Foo>(); 
type_id< map<string, pair<int, Bar> >(); 

Sí, esto le obliga a escribir una lista de todos los tipos involucrados, pero se puede echar en un encabezado, #include se entre ellos, y al menos evitar la duplicación de código. Esto también le absuelve de tener que idear ID únicos para cada tipo por su cuenta, como lo hace la respuesta de Johannes Schaub, aunque tiene la ventaja de que se realiza completamente en tiempo de compilación y, por lo tanto, está comprobado estáticamente por el compilador. Solo estoy ofreciendo una alternativa.

+0

Esto no funciona. Cuando tiene 'generate_type_id' templated por' T' siempre devolverá 0 (http://ideone.com/Ph3ha). Pero si lo convierte en una función sin plantilla, debería funcionar (http://ideone.com/zIIGb). Aunque es engorroso garantizar el mismo orden. – Nobody

+0

@ Nadie: Tienes razón. Lo actualizaré o eliminaré en algún momento. –

0

Un enfoque fácil podría ser simplemente compartir la misma clase en ambos programas.

La reutilización es uno de los objetivos de OOP.

Se puede crear una clase que encapsula el mapa y su inicialización y luego se usa en ambos programas C++.