is_specialization in Boost.Traits?

Is there something like a is_specialization in Boost.Traits? Something like: template <typename TypeT, template<typename> class TemplateTypeT> struct is_specialization { private: template <typename T> static char foo( TemplateTypeT<T>* ); static int foo( ... ); public: enum { value = (sizeof(is_specialization::foo((TypeT*)0)) == sizeof(char)) } ; }; It's very limited since it only supports a specific number of template arguments. The number of template arguments could be passed, but it would still cause problems with non-type template arguments. Any ideas? Maybe something like: BOOST_IS_SPECIALIZATION(type, templateType, signature) called like: BOOST_IS_SPECIALIZATION(myType, std::list, (typename, typename)) Regards, Nicolas

On 6/20/06, Nicolas Fleury <nidoizo@yahoo.com> 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

Matt Calabrese wrote:
On 6/20/06, Nicolas Fleury <nidoizo@yahoo.com> 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 ).
I totally agree. Yes, that's exactly what I mean.
(...) 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;
Sounds great. I think that's a good approach.
/* 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). */
I find it reasonable considering a typedef can be used as a workaround. Regards, Nicolas

Matt Calabrese wrote:
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
Matt, looks like you've got this sussed out, care to wrap it up and make it a submission complete with tests etc? John.

"Matt Calabrese" <rivorus@gmail.com> writes:
On 6/20/06, Nicolas Fleury <nidoizo@yahoo.com> 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".
No, "specialization" is the correct term here. Some people also say "instance" which is perhaps more descriptive, but "specialization" is the official term. Too bad the word is so overloaded. -- Dave Abrahams Boost Consulting www.boost-consulting.com

Nicolas Fleury <nidoizo@yahoo.com> writes:
Is there something like a is_specialization in Boost.Traits? Something like:
template <typename TypeT, template<typename> class TemplateTypeT> struct is_specialization { private: template <typename T> static char foo( TemplateTypeT<T>* ); static int foo( ... ); public: enum { value = (sizeof(is_specialization::foo((TypeT*)0)) == sizeof(char)) } ; };
It's very limited since it only supports a specific number of template arguments. The number of template arguments could be passed, but it would still cause problems with non-type template arguments. Any ideas?
Maybe something like: BOOST_IS_SPECIALIZATION(type, templateType, signature) called like: BOOST_IS_SPECIALIZATION(myType, std::list, (typename, typename))
See boost/detail/is_xxx.hpp -- Dave Abrahams Boost Consulting www.boost-consulting.com

Nicolas Fleury <nidoizo@yahoo.com> writes:
David Abrahams wrote:
See boost/detail/is_xxx.hpp
That's perfect, thx. Is that something we want to add to the documentation and move out of detail?
As Tonto said in the old joke, "who's `we,' white man?" -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Nicolas Fleury <nidoizo@yahoo.com> writes:
David Abrahams wrote:
See boost/detail/is_xxx.hpp
That's perfect, thx. Is that something we want to add to the documentation and move out of detail?
As Tonto said in the old joke, "who's `we,' white man?"
K, if we agree;), I'll submit a patch in next weeks to move it in boost/type_traits and update the doc. By default I assume we name the macro BOOST_IS_XXX_DEF. Regards, Nicolas

David Abrahams wrote:
Nicolas Fleury <nidoizo@yahoo.com> writes:
David Abrahams wrote:
See boost/detail/is_xxx.hpp
That's perfect, thx. Is that something we want to add to the documentation and move out of detail?
As Tonto said in the old joke, "who's `we,' white man?"
After looking more at it, I think Matt Calabrese implementation is better, since it would support also integers as template arguments. I also think it's better for something not in detail to not add automatically the is_ prefix. Regards, Nicolas
participants (4)
-
David Abrahams
-
John Maddock
-
Matt Calabrese
-
Nicolas Fleury