I am using C++ (not 11) and using some libraries which have different typedefs for integer data types. Is there any way I can assert that two typedefs are the same type? I've come up with the following solution myself.. is it safe? Thanks
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
}
Difference between typedef and #define: typedef is limited to giving symbolic names to types only, whereas #define can be used to define an alias for values as well, e.g., you can define 1 as ONE, 3.14 as PI, etc.
typedef simply lets you give a new name to an existing type. But that name combines every aspect of the existing type into an indivisible entity, such that e.g. ptype a, b; is equivalent to ptype a; ptype b; (and const ptype means "const pointer-to-int" because ptype means "pointer-to-int").
We can have symbolic names to datatypes using typedef but not to numbers etc. Whereas with a macro, we can represent 1 as ONE, 3.14 as PI and many more. We can have a type name and a variable name as same while using typedef. Compiler differentiates both.
There is no major difference between the two. 'Using' in C++ is considered to define the type synonyms. This method is also known as alias- declaration. Defining these alias-declaration works similar to defining the variables in C++ with 'using' statement.
In C++11, you could use std::is_same<T,U>::value
.
Since you don't have C++11, you could implement this functionality yourself as:
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;
};
Done!
Likewise you can implement static_assert
1 as:
template<bool> struct static_assert;
template<> struct static_assert<true> {}; //specialization
Now you can use them as:
static_assert<is_same<UINT64,UINT64>::value>(); //pass
static_assert<is_same<UINT64,UINT32>::value>(); //fail
Or you could wrap this in a macro as:
#define STATIC_ASSERT(x) { static_assert<x> static_assert_failed; (void) static_assert_failed; }
then use as:
STATIC_ASSERT(is_same<UINT64,UINT64>::value); //pass
STATIC_ASSERT(is_same<UINT64,UINT32>::value); //pass
If you use macro, then you would see the following string in the compiler generated message if the assert fails:
static_assert_failed
which is helpful. With the other information in the error message, you would be able to figure out why it failed.
Hope that helps.
1. Note that in C++11, static_assert
is an operator (which operates at compile-time), not a class template. In the above code, static_assert
is a class template.
Since you don't have C++11, use boost.
BOOST_STATIC_ASSERT(boost::is_same<T, U>::value);
You can write some kind of your assert function, instead of BOOST_STATIC_ASSERT
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With