1 | /* Copyright 2003-2013 Joaquin M Lopez Munoz. |
2 | * Distributed under the Boost Software License, Version 1.0. |
3 | * (See accompanying file LICENSE_1_0.txt or copy at |
4 | * http://www.boost.org/LICENSE_1_0.txt) |
5 | * |
6 | * See http://www.boost.org/libs/multi_index for library home page. |
7 | */ |
8 | |
9 | #ifndef BOOST_MULTI_INDEX_DETAIL_NO_DUPLICATE_TAGS_HPP |
10 | #define BOOST_MULTI_INDEX_DETAIL_NO_DUPLICATE_TAGS_HPP |
11 | |
12 | #if defined(_MSC_VER) |
13 | #pragma once |
14 | #endif |
15 | |
16 | #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ |
17 | #include <boost/mpl/fold.hpp> |
18 | #include <boost/mpl/set/set0.hpp> |
19 | |
20 | namespace boost{ |
21 | |
22 | namespace multi_index{ |
23 | |
24 | namespace detail{ |
25 | |
26 | /* no_duplicate_tags check at compile-time that a tag list |
27 | * has no duplicate tags. |
28 | * The algorithm deserves some explanation: tags |
29 | * are sequentially inserted into a mpl::set if they were |
30 | * not already present. Due to the magic of mpl::set |
31 | * (mpl::has_key is contant time), this operation takes linear |
32 | * time, and even MSVC++ 6.5 handles it gracefully (other obvious |
33 | * solutions are quadratic.) |
34 | */ |
35 | |
36 | struct duplicate_tag_mark{}; |
37 | |
38 | struct duplicate_tag_marker |
39 | { |
40 | template <typename MplSet,typename Tag> |
41 | struct apply |
42 | { |
43 | typedef mpl::s_item< |
44 | typename mpl::if_<mpl::has_key<MplSet,Tag>,duplicate_tag_mark,Tag>::type, |
45 | MplSet |
46 | > type; |
47 | }; |
48 | }; |
49 | |
50 | template<typename TagList> |
51 | struct no_duplicate_tags |
52 | { |
53 | typedef typename mpl::fold< |
54 | TagList, |
55 | mpl::set0<>, |
56 | duplicate_tag_marker |
57 | >::type aux; |
58 | |
59 | BOOST_STATIC_CONSTANT( |
60 | bool,value=!(mpl::has_key<aux,duplicate_tag_mark>::value)); |
61 | }; |
62 | |
63 | /* Variant for an index list: duplication is checked |
64 | * across all the indices. |
65 | */ |
66 | |
67 | struct duplicate_tag_list_marker |
68 | { |
69 | template <typename MplSet,typename Index> |
70 | struct apply:mpl::fold< |
71 | BOOST_DEDUCED_TYPENAME Index::tag_list, |
72 | MplSet, |
73 | duplicate_tag_marker> |
74 | { |
75 | }; |
76 | }; |
77 | |
78 | template<typename IndexList> |
79 | struct no_duplicate_tags_in_index_list |
80 | { |
81 | typedef typename mpl::fold< |
82 | IndexList, |
83 | mpl::set0<>, |
84 | duplicate_tag_list_marker |
85 | >::type aux; |
86 | |
87 | BOOST_STATIC_CONSTANT( |
88 | bool,value=!(mpl::has_key<aux,duplicate_tag_mark>::value)); |
89 | }; |
90 | |
91 | } /* namespace multi_index::detail */ |
92 | |
93 | } /* namespace multi_index */ |
94 | |
95 | } /* namespace boost */ |
96 | |
97 | #endif |
98 | |