2012-03-06 20 views
14

Me gustaría usar algo como typedef en mis programas C++ para mejorar la seguridad del tipo.typesafe typedef en C++

Como un ejemplo, supongamos que tengo dos funciones

void function1(unsigned idOfType1); 
void function2(unsigned idOfType2); 

entonces puedo pasar erróneamente idOfType2 a FUNCTION1 y viceversa. Quiero que el compilador me dé un error en este caso. Soy consciente de que podría envolver estos unsigned en una estructura, pero luego tendría que proporcionar un nombre de campo y usar . para acceder a ellos, lo cual es un poco incómodo. ¿Hay una buena forma de evitar esto?

Editar: Por lo que sé typedef no funcionará para este fin, ya que es solo una abreviatura de un tipo y no se utilizará para la verificación de tipos.

+2

Enums funcionan bien en su caso ... –

+0

@AlexanderPavlov se preocupan por elaborar, no es obvio para mí ... – Paul

+2

@Paul: puede escribir algo como 'enum Type1 {dummy0 = 1, dummy1 = 1 << 1, dummy2 = 1 < <2, ..., dummy31 = 1 << 31}; ', y suponiendo que' unsigned' es un tipo de 32 bits en su implementación, entonces el resultado es una enumeración que puede contener cualquier valor de 'unsigned'. Entonces 'void function1 (Type1 id)' no aceptará un 'Type2', porque las enum no son implícitamente convertibles entre sí. –

Respuesta

6

Como dices, un typedef no te ayudará aquí. No puedo pensar en una mejor manera de inmediato, sin embargo, si vas con tu envoltura en una opción struct/class, podrías usar un operador de conversión para eliminar el método de miembro o la llamada a función.

Por ejemplo:

struct WrappedType 
{ 
    operator type() 
    { 
     return _value; 
    } 

    type _value; 
} 

No digo que este es el camino hacerlo importa que ;-)

+1

¿Puede mostrarme cómo podría usar el operador de tipo? Boost strong typedef parece una buena opción en general, pero podría no funcionar en mi caso, ¡así que estoy interesado en esta solución! – Paul

+0

Por lo que tengo entendido, es exactamente lo que el tipo fuerte de boost hace ... – Griwes

+1

@Konrad genial! Gracias por elaborar. Si no puedo usar boost typedef fuerte entonces usaré esta solución. – Paul

15

Uso Boost strong typedef:

typedef crea un alias para un tipo existente. No crea un nuevo tipo que puede ser utilizado para hacer coincidir cualquiera de las funciones o parámetros de plantilla ...

Uso de BOOST_STRONG_TYPEDEF aborda este ...

BOOST_STRONG_TYPEDEF es una macro que genera una clase llamada envolturas "nombre" e instancia de su tipo primitivo y proporciona operadores de conversión apropiados para hacer que el nuevo tipo sea sustituible por el que envuelve.

+1

Debería tener revisó el impulso antes de preguntar ... ¡gracias por la respuesta rápida! – Paul

+0

Tenga en cuenta que Boost strong typedef permite la conversión implícita en las asignaciones. – larsch

0

Hay un C++ 11 enum class característica llamada, que es básicamente un tipo seguro enum. Quizás puedan ayudar aquí.

+1

'enum's siempre son seguros, p. Ej. 'enum x {a}; enum y {b}; y = a; 'no compilaría.- –

+1

@phresnel Creo que esto es solo verdad a medias, ya que las enumeraciones se convertirán implícitamente en enteros, ¿no? – Paul

+0

@Paul: concordamos en 0.75 * verdadero, ya que lo opuesto no es verdad. Entonces, parecería que las enumeraciones son 75% seguras, ... –

-2

Puede verificar el tipo en su función, de modo que si no coincide, puede imprimir un error o algo.

Puede utilizar typeid para detectar el tipo de variable, de la siguiente manera:

typeid(*variablename*).name() 

Como se sugiere en una de las respuestas here, esto es compilador dependiente y tiene que utilizar el método de tratar y error para encontrar qué valor funciona para ti

+1

Pero entonces tendría que hacer eso en __ todas__ llamadas a funciones + ¿depende el compilador? lo siento, no creo que esta sea una buena opción ... – Paul

+0

No funciona de todos modos: el tipo del parámetro 'idOfType1' en' function1' siempre es 'unsigned'. Lo que pasó la persona que llama ya se ha convertido. –

2

Lo quiero en el idioma. No es una respuesta en sí, pero ... :)

Opaque typedefs

1

Ésta es una respuesta tardía a una vieja pregunta.Pero hay nuevos desarrollos en la parte frontal C++ y en aras de la exhaustividad que estoy añadiendo esta respuesta:

El opaque_typedef biblioteca es el intento del autor para proporcionar la mayor parte del valor de typedefs opacos a través de una biblioteca, sin esperar a que typedefs opacos se convierta en una función de idioma.

El autor de esta biblioteca, Kyle Markley tenía short brilliant speech at the cppcon 2015 al introducir esta biblioteca. Las diapositivas de su discurso están en github el código fuente de la biblioteca está disponible en sourceforge. La biblioteca es solo de encabezado, escrita en C++ 11. Gcc y clang están bien, pero VS2015 parece tener problemas con eso.

El uso de la biblioteca es directo. El siguiente código fue tomado de la documentación. Crea un typedef opaco de int. Tiene la misma interfaz que un int (se puede añadir, desplazado, incrementado, en comparación, etc.), pero los argumentos y valores de retorno son del tipo recién creado, no de int:

#include "opaque/numeric_typedef.hpp" 

struct myint : opaque::numeric_typedef<int, myint> { 
    using base = opaque::numeric_typedef<int, myint>; 
    using base::base; 
};