3 #ifndef CDSLIB_OPT_OPTIONS_H
4 #define CDSLIB_OPT_OPTIONS_H
7 Framework to define template options
10 2011.01.23 khizmax Created
13 #include <stdlib.h> // rand, srand
15 #include <cds/details/aligned_type.h>
16 #include <cds/user_setup/allocator.h>
17 #include <cds/user_setup/cache_line.h>
18 #include <cds/algo/atomic.h>
22 /// Framework to define template options
24 There are two kind of options:
25 - \p type-option - option that determines a data type. The template argument \p Type of the option is a type.
26 - \p value-option - option that determines a value. The template argument \p Value of the option is a value.
30 /// Predefined options value (generally, for the options that determine the data types)
33 /// Type indicates that an option is not specified and the default one should be used
37 template <class Base> struct pack: public Base
42 /// Metafunction for selecting default option value
45 - \p Option - option value
46 - \p Default - default option value
47 - \p Value - option value if \p Option is not opt::none
49 If \p Option is opt::none, the metafunction result is \p Default, otherwise
50 the result is \p Value.
54 // default_spin is cds::sync::spin
55 typedef typename cds::opt::select_default< cds::opt::none, cds::sync::spin >::type default_spin;
57 // spin_32bit is cds::sync::reentrant_spin32
58 typedef typename cds::opt::select_default< cds::opt::none, cds::sync::reentrant_spin32 >::type spin_32bit;
61 template <typename Option, typename Default, typename Value = Option>
64 typedef Value type ; ///< metafunction result
67 template <typename Default>
68 struct select_default< none, Default >
74 /// Metafunction to select option value
76 This metafunction is intended for extracting the value of the \p Option option.
79 #include <cds/opt/options.h>
80 #include <type_traits> // only for testing purpose (static_assert)
85 typedef cds::opt::tag< tag_a > tag_option;
87 // What is the value of the tag_option?
88 // How we can extract tag_a from tag_option?
89 // Here is a solution:
90 typedef cds::opt::value< tag_option >::tag tag_option_value;
92 // tag_option_value is the same as tag_a
93 static_assert( std::is_same< tag_option_value, tag_a >::value, "Error: tag_option_value != tag_a" );
97 template <typename Option>
98 struct value: public Option::template pack<none>
102 /// [type-option] Option setter specifies a tag
104 Suppose, you have a struct
109 and you want that your class \p X would be derived from several \p Feature:
111 class X: public Feature, public Feature
115 How can you distinguish one \p Feature from another?
116 You may use a tag option:
118 template <typename Tag>
124 class X: public Feature< tag_a >, public Feature< tag_b >
127 Now you can distinguish one \p Feature from another:
130 Feature<tag_a>& fa = static_cast< Feature<tag_a> >( x );
131 Feature<tag_b>& fb = static_cast< Feature<tag_b> >( x );
134 \p tag option setter allows you to do things like this for an option-centric approach:
136 template <typename ...Options>
142 class X: public Feature< tag<tag_a> >, public Feature< tag<tag_b> >
146 This option setter is widely used in cds::intrusive containers to distinguish
147 between different intrusive part of container's node.
149 An incomplete type can serve as a \p Tag.
151 template <typename Tag>
154 template<class Base> struct pack: public Base
161 /// [type-option] Option setter specifies lock class
163 Specification of the \p Type class is:
171 template <typename Type>
174 template<class Base> struct pack: public Base
176 typedef Type lock_type;
181 /// [type-option] @ref cds_sync_monitor "Monitor" type setter
183 This option setter specifyes @ref cds_sync_monitor "synchronization monitor"
184 for blocking container.
186 template <typename Type>
187 struct sync_monitor {
189 template <class Base> struct pack : public Base
191 typedef Type sync_monitor;
196 /// [type-option] Back-off strategy option setter
198 Back-off strategy used in some algorithm.
199 See cds::backoff namespace for back-off explanation and supported interface.
201 template <typename Type>
204 template <class Base> struct pack: public Base
206 typedef Type back_off;
211 /// [type-option] Option setter for garbage collecting schema used
213 Possible values of \p GC template parameter are:
214 - cds::gc::HP - Hazard Pointer garbage collector
215 - cds::gc::DHP - Dynamic Hazard Pointer garbage collector
216 - cds::gc::none::GC - No garbage collector (not supported for some containers)
218 template <typename GC>
221 template <class Base> struct pack: public Base
228 /// [type-option] Option setter for an allocator
230 \p Type is allocator with \p std::allocator interface. Default is value of macro CDS_DEFAULT_ALLOCATOR
231 that, in turn, is \p std::allocator.
233 The \p libcds containers actively use rebinding to convert an allocator of one type to another. Thus,
234 you may specify any valid type as std::allocator's template parameter.
236 See also opt::node_allocator
238 template <typename Type>
241 template <typename Base> struct pack: public Base
243 typedef Type allocator;
248 /// [type-option] Option setter for node allocator
250 \p Type is allocator with \p std::allocator interface. Default is value of macro CDS_DEFAULT_ALLOCATOR
251 that, in turn, is \p std::allocator.
253 Many node-base containers require an allocator for maintaining data (container's node) and for internal use.
254 Sometimes, this types of allocator should be different for performance reason.
255 For example, we should like to allocate the node from a pool of preallocated nodes.
256 Such pool can be seen as the node allocator.
258 Usually, if a container supports \p opt::allocator and \p %opt::node_allocator options
259 and \p opt::node_allocator is not specified the \p %opt::allocator option is used for maintaining the nodes.
261 The \p libcds containers actively use rebinding to convert an allocator of one type to another. Thus,
262 you may specify any valid type as std::allocator's template parameter.
264 template <typename Type>
265 struct node_allocator {
267 template <typename Base> struct pack: public Base
269 typedef Type node_allocator;
274 /// [type-option] Option setter for item counting
276 Some data structure (for example, queues) has additional feature for item counting.
277 This option allows to set up appropriate item counting policy for that data structure.
279 Predefined option \p Type:
280 - atomicity::empty_item_counter - no item counting performed. It is default policy for many
282 - atomicity::item_counter - the class that provides atomically item counting
283 - opt::v::sequential_item_counter - simple non-atomic item counter. This item counter is not intended for
284 concurrent containers and may be used only if it is explicitly noted.
286 You may provide other implementation of atomicity::item_counter interface for your needs.
288 Note, the item counting in lock-free containers cannot be exact; for example, if
289 item counter for a container returns zero it is not mean that the container is empty.
290 Thus, item counter may be used for statistical purposes only.
292 template <typename Type>
293 struct item_counter {
295 template <typename Base> struct pack: public Base
297 typedef Type item_counter;
303 /// Sequential non-atomic item counter
305 This type of item counter is not intended for concurrent containers
306 and may be used only if it is explicitly noted.
308 class sequential_item_counter
311 typedef size_t counter_type ; ///< Counter type
313 counter_type m_nCounter ; ///< Counter
316 sequential_item_counter()
320 /// Returns current value of the counter
321 counter_type value() const
326 /// Same as \ref value() with relaxed memory ordering
327 operator counter_type() const
332 /// Increments the counter. Semantics: postincrement
338 /// Decrements the counter. Semantics: postdecrement
345 counter_type operator ++()
350 counter_type operator ++(int)
356 counter_type operator --()
361 counter_type operator --(int)
366 /// Resets count to 0
374 /// Special alignment constants for \ref cds::opt::alignment option
375 enum special_alignment {
376 no_special_alignment = 0, ///< no special alignment
377 cache_line_alignment = 1 ///< use cache line size defined in cds/user_setup/cache_line.h
380 /// [value-option] Alignment option setter
382 Alignment for some internal data of containers. May be useful to solve false sharing problem.
383 \p Value defines desired alignment and it may be power of two integer or predefined values from
384 \ref special_alignment enum.
386 template <unsigned int Value>
389 template <typename Base> struct pack: public Base
391 enum { alignment = Value };
398 template <typename Type, unsigned int Alignment>
399 struct alignment_setter {
400 typedef typename cds::details::aligned_type< Type, Alignment >::type type;
403 template <typename Type>
404 struct alignment_setter<Type, no_special_alignment> {
408 template <typename Type>
409 struct alignment_setter<Type, cache_line_alignment> {
410 typedef typename cds::details::aligned_type< Type, c_nCacheLineSize >::type type;
412 } // namespace details
415 /// Special padding constants for \p cds::opt::padding option
416 enum special_padding {
417 no_special_padding = 0, ///< no special padding
418 cache_line_padding = 1, ///< use cache line size defined in cds/user_setup/cache_line.h
420 /// Apply padding only for tiny data of size less than required padding
422 The flag means that if your data size is less than the casheline size, the padding is applyed.
423 Otherwise no padding will be applyed.
425 This flag is applyed for padding value:
427 cds::opt::padding< cds::opt::cache_line_padding | cds::opt::padding_tiny_data_only >;
428 cds::opt::padding< 256 | cds::opt::padding_tiny_data_only >;
431 padding_tiny_data_only = 0x80000000,
434 padding_flags = padding_tiny_data_only
438 /// [value-option] Padding option setter
440 The padding for the internal data of some containers. May be useful to solve false sharing problem.
441 \p Value defines desired padding and it may be power of two integer or predefined values from
442 \p special_padding enum.
444 template <unsigned int Value>
447 template <typename Base> struct pack: public Base
449 enum { padding = Value };
456 enum padding_vs_datasize {
457 padding_datasize_less,
458 padding_datasize_equal,
459 padding_datasize_greater
462 template < typename T, unsigned int Padding, bool NoPadding, padding_vs_datasize Relation, bool TinyOnly >
463 struct apply_padding_helper;
465 template <typename T, padding_vs_datasize Relation, bool TinyOnly >
466 struct apply_padding_helper < T, 0, true, Relation, TinyOnly >
471 typedef void padding_type;
474 template <typename T, unsigned int Padding, bool TinyOnly >
475 struct apply_padding_helper < T, Padding, false, padding_datasize_equal, TinyOnly >
480 typedef void padding_type;
483 template <typename T, unsigned int Padding, bool TinyOnly >
484 struct apply_padding_helper < T, Padding, false, padding_datasize_less, TinyOnly >
486 typedef uint8_t padding_type[Padding - sizeof( T )];
494 template <typename T, unsigned int Padding >
495 struct apply_padding_helper < T, Padding, false, padding_datasize_greater, false >
497 typedef uint8_t padding_type[Padding - sizeof( T ) % Padding];
504 template <typename T, unsigned int Padding >
505 struct apply_padding_helper < T, Padding, false, padding_datasize_greater, true >
510 typedef void padding_type;
513 template <typename T, unsigned int Padding >
517 enum { padding = Padding & ~padding_flags };
520 static CDS_CONSTEXPR const size_t c_nPadding =
521 static_cast<unsigned int>(padding) == static_cast<unsigned int>(cache_line_padding) ? cds::c_nCacheLineSize :
522 static_cast<unsigned int>(padding) == static_cast<unsigned int>(no_special_padding) ? 0 : padding;
524 static_assert( (c_nPadding & (c_nPadding - 1)) == 0, "Padding must be a power-of-two number" );
526 typedef apply_padding_helper< T,
529 sizeof( T ) < c_nPadding ? padding_datasize_less : sizeof( T ) == c_nPadding ? padding_datasize_equal : padding_datasize_greater,
530 (Padding & padding_tiny_data_only) != 0
533 typedef typename result::type type;
535 typedef typename std::conditional<
536 std::is_same< typename result::padding_type, void >::value,
538 typename result::padding_type
539 >::type padding_type;
542 } // namespace details
546 /// [type-option] Generic option setter for statisitcs
548 This option sets a type to gather statistics.
549 The option is generic - no predefined type(s) is provided.
550 The particular \p Type of statistics depends on internal structure of the object.
552 template <typename Type>
555 template <typename Base> struct pack: public Base
562 /// [type-option] Option setter for C++ memory model
564 The <b>cds</b> library supports following memory ordering constraints for atomic operations in container implementation:
565 - \p v::relaxed_ordering - relaxed C++ memory model. This mode supports full set of memory ordering constraints:
566 \p memory_order_relaxed, \p memory_order_acquire, \p memory_order_release and so on.
567 - \p v::sequential_consistent - sequentially consistent C++ memory model (default memory ordering for C++). In
568 this mode any memory ordering constraint maps to \p memory_order_seq_cst.
570 The \p Type template parameter can be \p v::relaxed_ordering or \p v::sequential_consistent.
572 You may mix different memory ordering options for different containers: one declare as sequentially consistent,
573 another declare as relaxed.
574 Usually, \p v::relaxed_ordering is the default memory ordering for <b>libcds</b> containers.
576 template <typename Type>
577 struct memory_model {
579 template <typename Base> struct pack: public Base
581 typedef Type memory_model;
587 /// Relaxed memory ordering model
589 In this memory model the memory constraints are defined according to C++ Memory Model specification:
590 each constraint is mapped to \p std::memory_order constraints one-to-one
592 See \p opt::memory_model for explanations
594 struct relaxed_ordering {
596 static const atomics::memory_order memory_order_relaxed = atomics::memory_order_relaxed;
597 static const atomics::memory_order memory_order_consume = atomics::memory_order_consume;
598 static const atomics::memory_order memory_order_acquire = atomics::memory_order_acquire;
599 static const atomics::memory_order memory_order_release = atomics::memory_order_release;
600 static const atomics::memory_order memory_order_acq_rel = atomics::memory_order_acq_rel;
601 static const atomics::memory_order memory_order_seq_cst = atomics::memory_order_seq_cst;
605 /// Sequential consistent memory ordering model
607 In this memory model any memory constraint is equivalent to \p memory_order_seq_cst.
609 See \p opt::memory_model for explanations
611 struct sequential_consistent {
613 static const atomics::memory_order memory_order_relaxed = atomics::memory_order_seq_cst;
614 static const atomics::memory_order memory_order_consume = atomics::memory_order_seq_cst;
615 static const atomics::memory_order memory_order_acquire = atomics::memory_order_seq_cst;
616 static const atomics::memory_order memory_order_release = atomics::memory_order_seq_cst;
617 static const atomics::memory_order memory_order_acq_rel = atomics::memory_order_seq_cst;
618 static const atomics::memory_order memory_order_seq_cst = atomics::memory_order_seq_cst;
623 /// Totally relaxed memory ordering model (do not use!)
625 In this memory model any memory constraint is equivalent to \p memory_order_relaxed.
626 @warning Do not use this model! It intended for testing purposes only
627 to verify debugging instruments like Thread Sanitizer.
629 See \p opt::memory_model for explanations
631 struct total_relaxed_ordering {
632 static const atomics::memory_order memory_order_relaxed = atomics::memory_order_relaxed;
633 static const atomics::memory_order memory_order_consume = atomics::memory_order_relaxed;
634 static const atomics::memory_order memory_order_acquire = atomics::memory_order_relaxed;
635 static const atomics::memory_order memory_order_release = atomics::memory_order_relaxed;
636 static const atomics::memory_order memory_order_acq_rel = atomics::memory_order_relaxed;
637 static const atomics::memory_order memory_order_seq_cst = atomics::memory_order_relaxed;
642 /// [type-option] Base type traits option setter
644 This option setter is intended generally for internal use for type rebinding.
646 template <typename Type>
649 template <typename Base> struct pack: public Base
651 typedef Type type_traits;
656 /// Resizing policy option
658 This option specifies the resizing policy that decides when to resize a container.
659 Used in some containers, for example, in container::StripedHashSet, intrusive::StripedHashSet.
661 The real resizing policy specified by \p Type does strongly depend on a container
662 that supports this option, see container documentation about possibly \p Type values.
664 template <typename Type>
665 struct resizing_policy {
667 template <typename Base> struct pack: public Base
669 typedef Type resizing_policy;
674 /// Copy policy option
676 The copy policy defines an item copying algorithm which is used, for example, when a container is resized.
677 It is very specific algorithm depending on type of the container.
679 template <typename Type>
682 template <typename Base> struct pack: public Base
684 typedef Type copy_policy;
689 /// Swap policy option
691 The swap policy specifies an algorithm for swapping two objects.
692 Usually, the default policy is \p std::swap (see opt::v::default_swap_policy):
696 template <typename T>
697 void operator ()( T& v1, T& v2 )
704 template <typename Type>
707 template <typename Base> struct pack: public Base
709 typedef Type swap_policy;
716 /// Default swap policy (see opt::swap_policy option)
718 The default swap policy is wrappr around \p std::swap algorithm.
720 struct default_swap_policy {
721 /// Performs swapping of \p v1 and \p v2 using \p std::swap algo
722 template <typename T>
723 void operator()( T& v1, T& v2 ) const
730 /// Move policy option
732 The move policy specifies an algorithm for moving object content.
733 In trivial case, it can be simple assignment.
735 The move interface is:
737 template <typename T>
739 void operator()( T& dest, T& src );
743 Note that in move algorithm the \p src source argument can be changed too.
744 So you can use move semantics.
746 Usually, the default move policy is opt::v::assignment_move_policy
748 template <typename Type>
751 template <typename Base> struct pack: public Base
753 typedef Type move_policy;
759 /// \ref opt::move_policy "Move policy" based on assignment operator
760 struct assignment_move_policy
762 /// <tt> dest = src </tt>
763 template <typename T>
764 void operator()( T& dest, T const& src ) const
771 /// [value-option] Enable sorting
773 This option enables (<tt>Enable = true</tt>) or disables (<tt>Enable == false</tt>)
774 sorting of a container.
776 template <bool Enable>
779 template <typename Base> struct pack: public Base
781 static bool const sort = Enable;
786 /// [type-option] Concurrent access policy
788 This option specifies synchronization strategy for fine-grained lock-based containers.
789 The option has no predefined \p Policy type.
790 For each container that accepts this option the range of available \p Policy types
793 template <typename Policy>
794 struct mutex_policy {
796 template <typename Base> struct pack: public Base
798 typedef Policy mutex_policy;
804 /// [type-option] Random number generator
806 The option specifies a random number generator.
807 \p Random can be any STL random number generator producing
808 unsigned integer: \p std::linear_congruential_engine,
809 \p std::mersenne_twister_engine, \p std::subtract_with_carry_engine
810 and so on, or opt::v::c_rand.
813 template <typename Random>
814 struct random_engine {
816 template <typename Base> struct pack: public Base
818 typedef Random random_engine;
824 /// \p rand() -base random number generator
826 This generator returns a pseudorandom integer in the range 0 to \p RAND_MAX (32767).
829 typedef unsigned int result_type; ///< Result type
831 /// Constructor initializes object calling \p srand()
837 /// Returns next random number calling \p rand()
838 result_type operator()()
840 return (result_type) rand();
847 template <typename Accessor>
848 struct key_accessor {
849 template <typename Base> struct pack: public Base
851 typedef Accessor key_accessor;
855 template <typename Traits, typename ReplaceWith, typename WhatReplace = none >
856 struct replace_key_accessor {
857 typedef typename std::conditional<
858 std::is_same< typename Traits::key_accessor, WhatReplace >::value,
859 typename opt::key_accessor< ReplaceWith >::template pack< Traits >,
865 }} // namespace cds::opt
869 // ****************************************************
870 // Options metafunctions
872 namespace cds { namespace opt {
876 template <typename OptionList, typename Option>
879 // Use "pack" member template to pack options
880 typedef typename Option::template pack<OptionList> type;
883 template <typename ...T> class typelist;
885 template <typename Typelist> struct typelist_head;
886 template <typename Head, typename ...Tail>
887 struct typelist_head< typelist<Head, Tail...> > {
890 template <typename Head>
891 struct typelist_head< typelist<Head> > {
895 template <typename Typelist> struct typelist_tail;
896 template <typename Head, typename ...Tail>
897 struct typelist_tail< typelist<Head, Tail...> > {
898 typedef typelist<Tail...> type;
900 template <typename Head>
901 struct typelist_tail< typelist<Head> > {
902 typedef typelist<> type;
905 template <typename OptionList, typename Typelist>
906 struct make_options_impl {
907 typedef typename make_options_impl<
910 typename typelist_head< Typelist >::type
912 typename typelist_tail<Typelist>::type
916 template <typename OptionList>
917 struct make_options_impl<OptionList, typelist<> > {
918 typedef OptionList type;
920 } // namespace details
923 /// make_options metafunction
924 /** @headerfile cds/opt/options.h
926 The metafunction converts option list \p Options to traits structure.
927 The result of metafunction is \p type.
929 Template parameter \p OptionList is default option set (default traits).
930 \p Options is option list.
932 template <typename OptionList, typename... Options>
933 struct make_options {
934 #ifdef CDS_DOXYGEN_INVOKED
935 typedef implementation_defined type ; ///< Result of the metafunction
937 typedef typename details::make_options_impl< OptionList, details::typelist<Options...> >::type type;
942 // *****************************************************************
943 // find_type_traits metafunction
944 // *****************************************************************
948 template <typename... Options>
949 struct find_type_traits_option;
952 struct find_type_traits_option<> {
953 typedef cds::opt::none type;
956 template <typename Any>
957 struct find_type_traits_option< Any > {
958 typedef cds::opt::none type;
961 template <typename Any>
962 struct find_type_traits_option< cds::opt::type_traits< Any > > {
966 template <typename Any, typename... Options>
967 struct find_type_traits_option< cds::opt::type_traits< Any >, Options... > {
971 template <typename Any, typename... Options>
972 struct find_type_traits_option< Any, Options... > {
973 typedef typename find_type_traits_option< Options... >::type type;
975 } // namespace details
978 /// Metafunction to find opt::type_traits option in \p Options list
979 /** @headerfile cds/opt/options.h
981 If \p Options contains \p opt::type_traits option then it is the metafunction result.
982 Otherwise the result is \p DefaultOptons.
984 template <typename DefaultOptions, typename... Options>
985 struct find_type_traits {
986 typedef typename select_default< typename details::find_type_traits_option<Options...>::type, DefaultOptions>::type type ; ///< Metafunction result
990 // *****************************************************************
991 // find_option metafunction
992 // *****************************************************************
996 template <typename What, typename... Options>
1000 struct compare_fail;
1002 template <typename A, typename B>
1003 struct compare_option
1005 typedef compare_fail type;
1008 template <template <typename> class Opt, typename A, typename B>
1009 struct compare_option< Opt<A>, Opt<B> >
1011 typedef compare_ok type;
1014 // Specializations for integral type of option
1015 #define CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_( _type ) template <template <_type> class What, _type A, _type B> \
1016 struct compare_option< What<A>, What<B> > { typedef compare_ok type ; };
1018 // For user-defined enum types
1019 #define CDS_DECLARE_FIND_OPTION_INTEGRAL_SPECIALIZATION( _type ) namespace cds { namespace opt { namespace details { CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(_type ) }}}
1021 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(bool)
1022 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(char)
1023 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned char)
1024 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(signed char)
1025 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(short int)
1026 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned short int)
1027 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(int)
1028 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned int)
1029 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(long)
1030 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned long)
1031 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(long long)
1032 CDS_FIND_OPTION_INTEGRAL_SPECIALIZATION_(unsigned long long)
1035 template <typename CompResult, typename Ok, typename Fail>
1036 struct select_option
1041 template <typename Ok, typename Fail>
1042 struct select_option< compare_ok, Ok, Fail >
1047 template <typename What>
1048 struct find_option< What > {
1052 template <typename What, typename Opt>
1053 struct find_option< What, Opt > {
1054 typedef typename select_option<
1055 typename compare_option< What, Opt >::type
1061 template <typename What, typename Opt, typename... Options>
1062 struct find_option< What, Opt, Options... > {
1063 typedef typename select_option<
1064 typename compare_option< What, Opt >::type
1066 ,typename find_option< What, Options... >::type
1069 } // namespace details
1072 /// Metafunction to find \p What option in \p Options list
1073 /** @headerfile cds/opt/options.h
1075 If \p Options contains \p What< Val > option for any \p Val then the result is \p What< Val >
1076 Otherwise the result is \p What.
1080 #include <cds/opt/options.h>
1081 namespace co = cds::opt;
1087 // Find option co::tag.
1089 // res1 is co::tag< tag_a >
1090 typedef co::find_option< co::tag< default_tag >, co::gc< cds::gc::HP >, co::tag< tag_a > >::type res1;
1092 // res2 is default co::tag< default_tag >
1093 typedef co::find_option< co::tag< default_tag >, co::less< x >, co::hash< H > >::type res2;
1095 // Multiple option co::tag. The first option is selected
1096 // res3 is default co::tag< tag_a >
1097 typedef co::find_option< co::tag< default_tag >, co::tag< tag_a >, co::tag< tag_b > >::type res3;
1101 template <typename What, typename... Options>
1102 struct find_option {
1103 typedef typename details::find_option<What, Options...>::type type ; ///< Metafunction result
1107 // *****************************************************************
1108 // select metafunction
1109 // *****************************************************************
1114 template <typename What, typename... Pairs>
1117 template <typename What, typename Value>
1118 struct select< What, What, Value>
1123 template <typename What, typename Tag, typename Value>
1124 struct select<What, Tag, Value>
1129 template <typename What, typename Value, typename... Pairs>
1130 struct select< What, What, Value, Pairs...>
1135 template <typename What, typename Tag, typename Value, typename... Pairs>
1136 struct select< What, Tag, Value, Pairs...>
1138 typedef typename select<What, Pairs...>::type type;
1140 } // namespace details
1143 /// Select option metafunction
1144 /** @headerfile cds/opt/options.h
1148 select <What, T1, R1, T2, R2, ... Tn, Rn> ::=
1149 if What == T1 then return R1
1150 if What == T2 then return R2
1152 if What == Tn then return Rn
1156 template <typename What, typename... Pairs>
1158 typedef typename details::select< What, Pairs...>::type type ; ///< Metafunction result
1161 }} // namespace cds::opt
1164 #endif // #ifndef CDSLIB_OPT_OPTIONS_H