2013-03-04 26 views
8

Używam C++ (nie 11) i przy użyciu niektórych bibliotek, które mają różne typy dla typów danych całkowitych. Czy jest jakiś sposób twierdzić, że dwa typy są tego samego typu? Sam wymyśliłem następujące rozwiązanie .. czy to jest bezpieczne? DziękiPorównaj typedef jest tego samego typu

template<typename T> 
struct TypeTest 
{ 
    static void Compare(const TypeTest& other) {} 
}; 

typedef unsigned long long UINT64; 
typedef unsigned long long UINT_64; 
typedef unsigned int UINT_32; 

int main() 
{ 
    TypeTest<UINT64>::Compare(TypeTest<UINT64>()); // pass 
    TypeTest<UINT64>::Compare(TypeTest<UINT_64>()); // pass 
    TypeTest<UINT64>::Compare(TypeTest<UINT_32>()); // fail 
} 
+2

cppreference ma przykładową implementację 'std :: is_same': http://en.cppreference.com/w/cpp/types/is_same – us2012

Odpowiedz

24

W C++ 11 można użyć std::is_same<T,U>::value.

Skoro nie masz C++ 11, można zaimplementować tę funkcjonalność siebie jako:

template<typename T, typename U> 
struct is_same 
{ 
    static const bool value = false; 
}; 

template<typename T> 
struct is_same<T,T> //specialization 
{ 
    static const bool value = true; 
}; 

Gotowe!

Podobnie można zaimplementować static_assert jak:

template<bool> struct static_assert; 
template<> struct static_assert<true> {}; //specialization 

Teraz można ich używać jako:

static_assert<is_same<UINT64,UINT64>::value>(); //pass 
static_assert<is_same<UINT64,UINT32>::value>(); //fail 

Lub można zawinąć to w makro jak:

#define STATIC_ASSERT(x) { static_assert<x> static_assert_failed; (void) static_assert_failed; } 

następnie użyć jako:

STATIC_ASSERT(is_same<UINT64,UINT64>::value); //pass 
STATIC_ASSERT(is_same<UINT64,UINT32>::value); //pass 

Jeśli używasz makro, wtedy można zobaczyć następujący ciąg znaków w wiadomości kompilatora generowany jeśli assert kończy się niepowodzeniem:

static_assert_failed 

która jest bardzo pomocna. Z innymi informacjami zawartymi w komunikacie o błędzie można dowiedzieć się, dlaczego się nie udało.

Nadzieję, że pomaga.


1. Należy zauważyć, że w C++ 11 static_assert jest operatorem (który działa w czasie kompilacji) nie szablon klasy. W powyższym kodzie static_assert jest szablonem klasy.

+0

Witam. Próbuję twoje rozwiązanie na VS2008, ale szablon linii static_assert daje błędy: błąd C4430: brak specyfikatora typu - int przyjęte. Uwaga: C++ nie obsługuje domyślnego-int błędu C2998: 'int static_assert': nie może być definicją szablonu –

+0

@NeilKirk: Ups. Zapomniałem 'struct' w definicji' static_assert'. Naprawiono to teraz. – Nawaz

+0

Powiedzmy, że UINT32 można zdefiniować unsigned int lub unsigned long int. Czy porównamy to samo w twoim kodzie? Dzięki. –

3

Ponieważ nie masz C++ 11, użyj boost.

BOOST_STATIC_ASSERT(boost::is_same<T, U>::value); 

Możesz napisać jakąś swojej funkcji assert, zamiast BOOST_STATIC_ASSERT.

+0

Podczas gdy używasz już boost, zastąp ciąg znaków run-time' assert 'z czasem kompilacji' BOOST_STATIC_ASSERT'. –

+0

@MichaelWild, assert nie jest prawdziwym dowodem, jest to swego rodzaju funkcja aserta. – ForEveR

+2

To nieistotne. Ważną rzeczą jest to, że OP prawdopodobnie chce, aby 'assert' przeszedł/zawiedzie podczas kompilacji, a nie podczas pracy. –

1

std :: type_info może Ci pomóc.

+0

Co to jest C++ 11 ... –

+0

@MichaelWild: Według strony [this] (http://www.cplusplus.com/reference/typeinfo/type_info/) nie jest to C++ 11 specifc. Czy mam rację ? – Kamouth

+0

Przepraszam, pomyliłem to z nagłówkiem ''. –

Powiązane problemy