2012-03-06 46 views
14

Chciałbym użyć czegoś podobnego do typedef w moich programach w C++, aby zwiększyć bezpieczeństwo typów.typesafe typedef w C++

Jako przykład, przypuśćmy że dwa zadania

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

następnie można omyłkowo przechodzą idOfType2 do Function1 i vice versa. Chcę, aby kompilator dał mi błąd w tym przypadku. Jestem świadomy, że mógłbym zawinąć te niepodpisane w struct, ale wtedy musiałbym podać nazwę pola i użyć ., aby uzyskać do nich dostęp, co jest nieco niewygodne. Czy istnieje dobry sposób obejścia tego?

Edycja: O ile mi wiadomo, typedef nie będzie działać w tym celu, ponieważ jest skrótem dla typu i nie będzie używany do sprawdzania typu.

+2

wyliczenia działa dobrze w twoim przypadku ... –

+0

@AlexanderPawlowska troska o szczegóły, nie jest dla mnie oczywista ... – Paul

+2

@Paul: możesz napisać coś w rodzaju 'enum Type1 {dummy0 = 1, dummy1 = 1 << 1, dummy2 = 1 < <2, ..., dummy31 = 1 << 31}; ', i zakładając' unsigned' jest 32-bitowym typem twojej implementacji, wynikiem jest wyliczenie, które może zawierać dowolną wartość 'unsigned'. Wtedy 'void function1 (Type1 id)' nie zaakceptuje 'Type2', ponieważ enums nie są niejawnie wymienialne dla siebie. –

Odpowiedz

6

Tak jak mówisz, typedef nie pomoże ci tutaj. Nie mogę wymyślić lepszego sposobu od razu, jednak jeśli użyjesz swojego zawijania w opcji struct/class, możesz użyć operatora konwersji, aby wyeliminować metodę elementu lub wywołanie funkcji.

Na przykład:

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

    type _value; 
} 

Nie mówię, że to jest sposób zrobić to przeszkadza Ci ;-)

+1

czy możesz pokazać mi, w jaki sposób mogę użyć operatora typu? Boost silny typedef wygląda ogólnie na dobrą opcję, ale Jeśli nie rozumiem, to interesuje mnie to rozwiązanie! – Paul

+0

O ile rozumiem, to właśnie to jest silne wzmocnienie typedef ... – Griwes

+1

@Konrad świetnie! Dzięki za opracowanie. Jeśli nie mogę użyć wzmocnienia silnym typedef wtedy użyję tego rozwiązania – Paul

15

Zastosowanie Boost strong typedef:

typedef tworzy alias dla istniejącego typu. Nie tworzy nowy typ, który może być używany do dopasowania ani funkcji lub parametrów szablonu ...

Wykorzystanie BOOST_STRONG_TYPEDEF rozwiązuje ten ...

BOOST_STRONG_TYPEDEF jest makro, które generuje klasę o nazwie „nazwa” okłady oraz przykład jego pierwotnego typu i zapewnia odpowiednie operatory konwersji, aby nowy typ mógł być zastępowalny dla tego, który się otacza.

+1

Powinienem Cię zainteresować. sprawdzone zwiększenie przed pytaniem ... dziękuję za szybką odpowiedź! – Paul

+0

Należy pamiętać, że Zwiększenie silnego typedef umożliwia niejawną konwersję w zadaniach – larsch

0

Jest C++ 11 funkcja o nazwie enum class, który jest zasadniczo jest to rodzaj wyliczenia bezpiecznego. Może oni mogą pomóc tutaj.

+1

'wyliczenia są zawsze chronione przed atakami, np. 'enum x {a}; enum y {b}; y = a; 'nie skompilowałoby się.- –

+1

@phresnel Myślę, że jest to tylko półprawda, ponieważ wyliczenia będą niejawnie konwertowane na ints, nie? – Paul

+0

@Paul: Zgadzamy się na 0.75 * prawda, ponieważ przeciwieństwo nie jest prawdą. Więc wydaje się, że wyliczenia są w 75% bezpieczne, ... –

-2

Możesz sprawdzić typ swojej funkcji, aby w razie niezgodności można było wydrukować błąd lub coś podobnego.

Można użyć typeid wykryć typ zmiennej, jak następuje:

typeid(*variablename*).name() 

Jak sugeruje w jednym z odpowiedziami here, to kompilator zależne i trzeba użyć metody prób i błędów, aby znaleźć która wartość działa dla Ciebie.

+1

Ale musiałbym to zrobić w __every__ wywołaniu funkcji + zależnym od kompilatora? przepraszam, nie sądzę, że to jest dobry wybór ... – Paul

+0

Nie działa mimo to - typ parametru "idOfType1" w "function1' jest zawsze" unsigned ". To, co zostało przekazane przez osobę dzwoniącą, zostało już przekonwertowane. –

1

To późno odpowiedź na starym pytaniem.Ale są nowe wydarzenia na C++ przed i w trosce o kompletność Dodaję tej odpowiedzi:

opaque_typedef biblioteka jest próba autora, aby zapewnić najbardziej wartości kryjących typedefs przez biblioteki, bez czekania na nieprzejrzysty typedefs, aby stać się funkcją językową.

Autor tej biblioteki, Kyle Markley, wprowadził bibliotekę short brilliant speech at the cppcon 2015. Slajdy jego przemówienia znajdują się pod numerem github, kod źródłowy biblioteki jest dostępny pod adresem sourceforge. Biblioteka jest tylko nagłówkowa, napisana w C++ 11. Gcc i clang są ok, ale VS2015 wydaje się mieć z tym problemy.

Korzystanie z biblioteki jest proste. Poniższy kod został zaczerpnięty z dokumentacji. Tworzy nieprzezroczysty typedef z int. Ma ten sam interfejs jako int (można go dodawać, przesunięte, zwiększana w porównaniu itp), ale argumenty i zwracane wartości są nowo utworzonego typu, nie stanowi int:

#include "opaque/numeric_typedef.hpp" 

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