|
Boost : |
From: Howard Hinnant (hinnant_at_[hidden])
Date: 1999-12-13 10:08:54
scleary_at_[hidden] wrote on 12/13/99 8:40 AM
>P.S. Howard - I like the compressed_pair name -- that's what empty_member
>has been evolving towards. Did you specialize call_traits/fundamentals for
>every standard builtin type?
Yes, I specialized type_traits on every builtin type and all 4 cv
variations thereof. I'll post it as an example of how I don't think it
should be done! :-)
// type_traits
// Using John's cv magic here
template <typename T> struct cv_traits_aux;
template <typename T>
struct cv_traits_aux<T*>
{
typedef T cv_unqualified;
};
template <typename T>
struct cv_traits_aux<const T*>
{
typedef T cv_unqualified;
};
template <typename T>
struct cv_traits_aux<volatile T*>
{
typedef T cv_unqualified;
};
template <typename T>
struct cv_traits_aux<const volatile T*>
{
typedef T cv_unqualified;
};
enum etype {integral_type, floating_type, void_type,
array_type, pointer_type, reference_type,
enum_type, class_type, union_type, member_ptr_type};
template <typename T>
struct type_traits
{
static const etype type = class_type;
static const bool has_trivial_default = false;
static const bool has_trivial_copy = false;
static const bool has_trivial_assign = false;
static const bool has_trivial_destructor = false;
typedef cv_traits_aux<T*>::cv_unqualified cv_unqualified;
};
#define _MAKE_TYPE_TRAITS(t1, t2) \
template <> \
struct type_traits<t1> \
{ \
static const etype type = t2; \
static const bool has_trivial_default = true; \
static const bool has_trivial_copy = true; \
static const bool has_trivial_assign = true; \
static const bool has_trivial_destructor = true; \
typedef t1 cv_unqualified; \
}; \
\
template <> \
struct type_traits<t1 const> \
{ \
static const etype type = t2; \
static const bool has_trivial_default = true; \
static const bool has_trivial_copy = true; \
static const bool has_trivial_assign = false; \
static const bool has_trivial_destructor = true; \
typedef t1 cv_unqualified; \
}; \
\
template <> \
struct type_traits<t1 volatile> \
{ \
static const etype type = t2; \
static const bool has_trivial_default = true; \
static const bool has_trivial_copy = true; \
static const bool has_trivial_assign = true; \
static const bool has_trivial_destructor = true; \
typedef t1 cv_unqualified; \
}; \
\
template <> \
struct type_traits<t1 const volatile> \
{ \
static const etype type = t2; \
static const bool has_trivial_default = true; \
static const bool has_trivial_copy = true; \
static const bool has_trivial_assign = false; \
static const bool has_trivial_destructor = true; \
typedef t1 cv_unqualified; \
};
_MAKE_TYPE_TRAITS(bool, integral_type)
_MAKE_TYPE_TRAITS(char, integral_type)
_MAKE_TYPE_TRAITS(signed char, integral_type)
_MAKE_TYPE_TRAITS(unsigned char, integral_type)
...
#undef _MAKE_TYPE_TRAITS
template <typename T>
struct type_traits<T*>
{
static const etype type = pointer_type;
static const bool has_trivial_default = true;
static const bool has_trivial_copy = true;
static const bool has_trivial_assign = true;
static const bool has_trivial_destructor = true;
typedef T* cv_unqualified;
};
template <typename T>
struct type_traits<T* const>
{
static const etype type = pointer_type;
static const bool has_trivial_default = true;
static const bool has_trivial_copy = true;
static const bool has_trivial_assign = false;
static const bool has_trivial_destructor = true;
typedef T* cv_unqualified;
};
...
template <typename T>
struct type_traits<T&>
{
static const etype type = reference_type;
static const bool has_trivial_default = false;
static const bool has_trivial_copy = true;
static const bool has_trivial_assign = false;
static const bool has_trivial_destructor = true;
typedef T& cv_unqualified;
};
template <typename T>
struct type_traits<T& const>
{
static const etype type = reference_type;
static const bool has_trivial_default = false;
static const bool has_trivial_copy = true;
static const bool has_trivial_assign = false;
static const bool has_trivial_destructor = true;
typedef T& cv_unqualified;
};
...
template <typename T, _STD::size_t sz>
struct type_traits<T[sz]>
{
static const etype type = array_type;
static const bool has_trivial_default = true;
static const bool has_trivial_copy = false;
static const bool has_trivial_assign = false;
static const bool has_trivial_destructor = true;
typedef T cv_unqualified[sz];
};
template <typename T, _STD::size_t sz>
struct type_traits<const T[sz]>
{
static const etype type = array_type;
static const bool has_trivial_default = false;
static const bool has_trivial_copy = false;
static const bool has_trivial_assign = false;
static const bool has_trivial_destructor = true;
typedef T cv_unqualified[sz];
};
...
Once all this is in place, call_traits isn't too bad and works for cv
qualified types. I was going to hold off on submitting it till the
"fundamentals" were in place, but here is how I've got it today:
template <typename T>
struct call_trait_aux
{
static const bool is_small_and_fast = type_traits<T>::has_trivial_copy
&& sizeof(T) <= sizeof(void*);
static const bool is_specialized = type_traits<T>::type == integral_type
|| type_traits<T>::type == floating_type
|| type_traits<T>::type == reference_type
|| type_traits<T>::type == array_type;
};
template <typename T, bool PassByValue =
call_trait_aux<T>::is_small_and_fast
||
call_trait_aux<T>::is_specialized>
struct call_traits
{
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef const_reference param_type;
};
template <typename T>
struct call_traits<T&, true>
{
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef reference param_type;
};
template <typename T>
struct call_traits<T& const, true>
{
typedef T value_type;
typedef T& const reference;
typedef const T& const const_reference;
typedef reference param_type;
};
template <typename T>
struct call_traits<T& volatile, true>
{
typedef T value_type;
typedef T& volatile reference;
typedef const T& volatile const_reference;
typedef reference param_type;
};
template <typename T>
struct call_traits<T& const volatile, true>
{
typedef T value_type;
typedef T& const volatile reference;
typedef const T& const volatile const_reference;
typedef reference param_type;
};
template <typename T, _CSTD::size_t sz>
struct call_traits<T[sz], true>
{
typedef const T* value_type;
typedef T(&reference)[sz];
typedef const T(&const_reference)[sz];
typedef value_type param_type;
};
template <typename T, _CSTD::size_t sz>
struct call_traits<const T[sz], true>
{
typedef const T* value_type;
typedef const T(&reference)[sz];
typedef const T(&const_reference)[sz];
typedef value_type param_type;
};
template <typename T, _CSTD::size_t sz>
struct call_traits<volatile T[sz], true>
{
typedef const volatile T* value_type;
typedef volatile T(&reference)[sz];
typedef const volatile T(&const_reference)[sz];
typedef value_type param_type;
};
template <typename T, _CSTD::size_t sz>
struct call_traits<const volatile T[sz], true>
{
typedef const volatile T* value_type;
typedef const volatile T(&reference)[sz];
typedef const volatile T(&const_reference)[sz];
typedef value_type param_type;
};
template <typename T>
struct call_traits<T, true>
{
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef T const param_type;
};
>I've been trying to get a specialization
>working that would allow us to determine if a type is empty or not, but
>haven't gotten anything to work. . .
Your is_empty is easy to extend now (except of course that enums break
it):
template <typename T>
struct can_derive_from
{
static const bool value = type_traits<T>::type == class_type
|| type_traits<T>::type == union_type;
};
template <typename T, bool b = can_derive_from<T>::value>
struct is_empty_imp
: T
{
int data_;
};
template <typename T>
struct is_empty_imp<T, false>
{
T data1_;
int data2_;
};
template <typename T>
struct is_empty
{
static const bool value = sizeof(is_empty_imp<T>) == sizeof(int);
};
#include <iostream>
struct A
{
};
int main()
{
std::cout << is_empty<A>::value << '\n';
std::cout << is_empty<A&>::value << '\n';
std::cout << is_empty<int>::value << '\n';
}
-Howard
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk