I was thinking to be more pedantic in choosing data type in a block of code where I would need to choose between size_type
size_t
in general or container::size_type
for container types. My problem is that if I have the following block of code, I don't know how to do it. Can anybody there help?
template<typename some_container>
int func(some_container& input)
{
//Some code...
//...
decltype(input.size()) variable_x; //Choose this if defined,
size_t variable_x; //otherwise choose this
//... Some more code...
}
In this case some_container
may be a custom container and does not provide size()
function. What led me to this thinking was reading the difference between size_t
and container::size_type
at size_t vs container::size_type. I also read Determine if a type is an STL container at compile time, but the approach feels a bit heavy-handed for my situation.
Following is one way to determine if a class
contains a type (e.g. size_type
) or not:
template <typename T>
struct Has_size_type
{
typedef char (&yes)[2];
template <typename C> static yes test(typename C::size_type*);
template <typename> static char test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
And following is the way to choose between 2 types:
template<bool> struct Bool;
template<typename T, typename = Bool<true> >
struct Set { typedef size_type type; };
template<typename T>
struct Set<T,Bool<Has_size_type<T>::value> > { typedef typename T::size_type type; };
Edit start: Here is another simpler approach:
template<typename T>
struct void_ { typedef void type; };
template<typename T, typename = void>
struct Set
{ typedef size_type type; };
template<typename T>
struct Set<T,typename void_<typename T::size_type>::type>
{ typedef typename T::size_type type; };
Edit end.
So finally, use as below:
template<typename some_container>
int func(some_container& input)
{
typedef typename Set<some_container>::type type;
}
So now type
is either size_type
or some_container::size_type
, if it has that.