Boost logo

Boost :

From: Matt Calabrese (rivorus_at_[hidden])
Date: 2006-06-21 16:01:00


On 6/20/06, Nicolas Fleury <nidoizo_at_[hidden]> wrote:
>
> Is there something like a is_specialization in Boost.Traits?

>From your example, I believe you mean "is instantation of" not "is
specialization of". If so, I do agree that such a metafunction would be
useful, as I find myself rolling my own similar metafunctions every once in
a while. However, your example incorrectly assumes that char and int are
different sizes ( sizeof(int) can yield 1 in a compliant C++ implementation
). Instead, prefer using type_traits's yes/no types or use array
reference types
or something similar.

Another simple implementation would be to just use
partial template specialization:

template< typename Type, template< typename > class Template >
struct is_instantiation_of
  : false_type
{
};

template< typename Arg, template< typename > class Template >
struct is_instantiation_of< Template< Arg >, Template >
   : true_type
{
};

/////////////////////////

// And a more modular form

/////////////////////////

#define BOOST_MAX_INSTANTIATION_OF_PARAMS 10

#define BOOST_DETAIL_IS_INSTANTIATION_OF( z, num_params, dummy ) \
template< typename Type \
, template< BOOST_PP_ENUM_PARAMS_Z \
( z, num_params, typename BOOST_PP_INTERCEPT ) > \
class Template > \
struct BOOST_PP_CAT( is_instantiation_of, num_params ) \
  : false_type \
{ \
}; \
 \
template< BOOST_PP_ENUM_PARAMS_Z( z, num_params, typename Arg ) \
, template< BOOST_PP_ENUM_PARAMS_Z \
( z, num_params, typename BOOST_PP_INTERCEPT ) > \
class Template > \
struct BOOST_PP_CAT( is_instantiation_of, num_params ) \
< Template< BOOST_PP_ENUM_PARAMS_Z( z, num_params, Arg ) > \
, Template > \
   : true_type \
{ \
};

BOOST_PP_REPEAT_FROM_TO
( 1, BOOST_PP_INC( BOOST_MAX_INSTANTIATION_OF_PARAMS )
, BOOST_DETAIL_IS_INSTANTIATION_OF
, BOOST_PP_NIL
)

#undef BOOST_DETAIL_IS_INSTANTIATION_OF

///////////////////////////

/* To account for templates which have non-type template parameters,
the best you could probably do is make a metafunction-generator
macro which goes on a per-template basis:*/

///////////////////////////

#define BOOST_GENERATE_IS_INSTANTIATION_OF( meta_name, template_name, params
) \
template< typename Type > \
struct meta_name \
  : false_type \
{ \
}; \
\
template< BOOST_SEQ_FOR_EACH_I \
( BOOST_DETAIL_GEN_IS_INST_PARAM, BOOST_PP_NIL, params ) > \
struct meta_name< template_name< BOOST_PP_ENUM_PARAMS \
( BOOST_PP_SEQ_SIZE( params ), Arg ) > > \
  : true_type \
{ \
};

#define BOOST_DETAIL_GEN_IS_INST_PARAM( r, dummy, index, kind ) \
kind BOOST_PP_CAT( Arg, index )

/////////////////////////////

// Usage would be:

/////////////////////////////

BOOST_GENERATE_IS_INSTANTIATION_OF
( is_boost_array, array, (typename)(::std::size_t) )

// Then use somewhere else
bool const value = ::boost::is_boost_array< ::boost::array< int, 10 >
>::value;

/*
The above macro would have a limitation being that a comma
cannot appear directly inside one of the sequence elements
of the last argument (so, i.e. the type can't come from a
metafunction invocation which takes more than one argument
explicitly unless additional measures are taken).
*/

-- 
-Matt Calabrese

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk