+
+
+ // *****************************************************************
+ // find_option metafunction
+ // *****************************************************************
+
+ //@cond
+ namespace details {
+ template <typename What, typename... Options>
+ struct find_option;
+
+ struct compare_ok;
+ struct compare_fail;
+
+ template <typename A, typename B>
+ struct compare_option
+ {
+ typedef compare_fail type;
+ };
+
+ template <template <typename> class Opt, typename A, typename B>
+ struct compare_option< Opt<A>, Opt<B> >
+ {
+ typedef compare_ok type;
+ };
+
+ // Specializations for integral type of option
+#define CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_( _type ) template <template <_type> class What, _type A, _type B> \
+ struct compare_option< What<A>, What<B> > { typedef compare_ok type ; };
+
+ // For user-defined enum types
+#define CDS_DECLARE_FIND_OPTION_INTEGRAL_SPECIALIZATION( _type ) namespace cds { namespace opt { namespace details { CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(_type ) }}}
+
+ CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(bool)
+ CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(char)
+ CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned char)
+ CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(signed char)
+ CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(short int)
+ CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned short int)
+ CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(int)
+ CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned int)
+ CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(long)
+ CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned long)
+ CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(long long)
+ CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned long long)
+
+
+ template <typename CompResult, typename Ok, typename Fail>
+ struct select_option
+ {
+ typedef Fail type;
+ };
+
+ template <typename Ok, typename Fail>
+ struct select_option< compare_ok, Ok, Fail >
+ {
+ typedef Ok type;
+ };
+
+ template <typename What>
+ struct find_option< What > {
+ typedef What type;
+ };
+
+ template <typename What, typename Opt>
+ struct find_option< What, Opt > {
+ typedef typename select_option<
+ typename compare_option< What, Opt >::type
+ ,Opt
+ ,What
+ >::type type;
+ };
+
+ template <typename What, typename Opt, typename... Options>
+ struct find_option< What, Opt, Options... > {
+ typedef typename select_option<
+ typename compare_option< What, Opt >::type
+ ,Opt
+ ,typename find_option< What, Options... >::type
+ >::type type;
+ };
+ } // namespace details
+ //@endcond
+
+ /// Metafunction to find \p What option in \p Options list
+ /** @headerfile cds/opt/options.h
+
+ If \p Options contains \p What< Val > option for any \p Val then the result is \p What< Val >
+ Otherwise the result is \p What.
+
+ Example:
+ \code
+ #include <cds/opt/options.h>
+ namespace co = cds::opt;
+
+ struct default_tag;
+ struct tag_a;
+ struct tag_b;
+
+ // Find option co::tag.
+
+ // res1 is co::tag< tag_a >
+ typedef co::find_option< co::tag< default_tag >, co::gc< cds::gc::HP >, co::tag< tag_a > >::type res1;
+
+ // res2 is default co::tag< default_tag >
+ typedef co::find_option< co::tag< default_tag >, co::less< x >, co::hash< H > >::type res2;
+
+ // Multiple option co::tag. The first option is selected
+ // res3 is default co::tag< tag_a >
+ typedef co::find_option< co::tag< default_tag >, co::tag< tag_a >, co::tag< tag_b > >::type res3;
+
+ \endcode
+ */
+ template <typename What, typename... Options>
+ struct find_option {
+ typedef typename details::find_option<What, Options...>::type type ; ///< Metafunction result
+ };
+
+
+ // *****************************************************************
+ // select metafunction
+ // *****************************************************************
+
+ //@cond
+ namespace details {
+
+ template <typename What, typename... Pairs>
+ struct select;
+
+ template <typename What, typename Value>
+ struct select< What, What, Value>
+ {
+ typedef Value type;
+ };
+
+ template <typename What, typename Tag, typename Value>
+ struct select<What, Tag, Value>
+ {
+ typedef What type;
+ };
+
+ template <typename What, typename Value, typename... Pairs>
+ struct select< What, What, Value, Pairs...>
+ {
+ typedef Value type;
+ };
+
+ template <typename What, typename Tag, typename Value, typename... Pairs>
+ struct select< What, Tag, Value, Pairs...>
+ {
+ typedef typename select<What, Pairs...>::type type;
+ };
+ } // namespace details