Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:58

0001 /*!
0002 @file
0003 Forward declares `boost::hana::Searchable`.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
0008  */
0009 
0010 #ifndef BOOST_HANA_FWD_CONCEPT_SEARCHABLE_HPP
0011 #define BOOST_HANA_FWD_CONCEPT_SEARCHABLE_HPP
0012 
0013 #include <boost/hana/config.hpp>
0014 
0015 
0016 namespace boost { namespace hana {
0017     //! @ingroup group-concepts
0018     //! @defgroup group-Searchable Searchable
0019     //! The `Searchable` concept represents structures that can be searched.
0020     //!
0021     //! Intuitively, a `Searchable` is any structure, finite or infinite,
0022     //! containing elements that can be searched using a predicate. Sometimes,
0023     //! `Searchable`s will associate keys to values; one can search for a key
0024     //! with a predicate, and the value associated to it is returned. This
0025     //! gives rise to map-like data structures. Other times, the elements of
0026     //! the structure that are searched (i.e. those to which the predicate is
0027     //! applied) are the same that are returned, which gives rise to set-like
0028     //! data structures. In general, we will refer to the _keys_ of a
0029     //! `Searchable` structure as those elements that are used for searching,
0030     //! and to the _values_ of a `Searchable` as those elements that are
0031     //! returned when a search is successful. As was explained, there is no
0032     //! requirement that both notions differ, and it is often useful to have
0033     //! keys and values coincide (think about `std::set`).
0034     //!
0035     //! Some methods like `any_of`, `all_of` and `none_of` allow simple queries
0036     //! to be performed on the keys of the structure, while other methods like
0037     //! `find` and `find_if` make it possible to find the value associated
0038     //! to a key. The most specific method should always be used if one
0039     //! cares about performance, because it is usually the case that heavy
0040     //! optimizations can be performed in more specific methods. For example,
0041     //! an associative data structure implemented as a hash table will be much
0042     //! faster to access using `find` than `find_if`, because in the second
0043     //! case it will have to do a linear search through all the entries.
0044     //! Similarly, using `contains` will likely be much faster than `any_of`
0045     //! with an equivalent predicate.
0046     //!
0047     //! > __Insight__\n
0048     //! > In a lazy evaluation context, any `Foldable` can also become a model
0049     //! > of `Searchable` because we can search lazily through the structure
0050     //! > with `fold_right`. However, in the context of C++, some `Searchable`s
0051     //! > can not be folded; think for example of an infinite set.
0052     //!
0053     //!
0054     //! Minimal complete definition
0055     //! ---------------------------
0056     //! `find_if` and `any_of`
0057     //!
0058     //! When `find_if` and `any_of` are provided, the other functions are
0059     //! implemented according to the laws explained below.
0060     //!
0061     //! @note
0062     //! We could implement `any_of(xs, pred)` by checking whether
0063     //! `find_if(xs, pred)` is an empty `optional` or not, and then reduce
0064     //! the minimal complete definition to `find_if`. However, this is not
0065     //! done because that implementation requires the predicate of `any_of`
0066     //! to return a compile-time `Logical`, which is more restrictive than
0067     //! what we have right now.
0068     //!
0069     //!
0070     //! Laws
0071     //! ----
0072     //! In order for the semantics of the methods to be consistent, some
0073     //! properties must be satisfied by any model of the `Searchable` concept.
0074     //! Rigorously, for any `Searchable`s  `xs` and `ys` and any predicate `p`,
0075     //! the following laws should be satisfied:
0076     //! @code
0077     //!     any_of(xs, p) <=> !all_of(xs, negated p)
0078     //!                   <=> !none_of(xs, p)
0079     //!
0080     //!     contains(xs, x) <=> any_of(xs, equal.to(x))
0081     //!
0082     //!     find(xs, x) == find_if(xs, equal.to(x))
0083     //!     find_if(xs, always(false_)) == nothing
0084     //!
0085     //!     is_subset(xs, ys) <=> all_of(xs, [](auto x) { return contains(ys, x); })
0086     //!     is_disjoint(xs, ys) <=> none_of(xs, [](auto x) { return contains(ys, x); })
0087     //! @endcode
0088     //!
0089     //! Additionally, if all the keys of the `Searchable` are `Logical`s,
0090     //! the following laws should be satisfied:
0091     //! @code
0092     //!     any(xs)  <=> any_of(xs, id)
0093     //!     all(xs)  <=> all_of(xs, id)
0094     //!     none(xs) <=> none_of(xs, id)
0095     //! @endcode
0096     //!
0097     //!
0098     //! Concrete models
0099     //! ---------------
0100     //! `hana::map`, `hana::optional`, `hana::range`, `hana::set`,
0101     //! `hana::string`, `hana::tuple`
0102     //!
0103     //!
0104     //! Free model for builtin arrays
0105     //! -----------------------------
0106     //! Builtin arrays whose size is known can be searched as-if they were
0107     //! homogeneous tuples. However, since arrays can only hold objects of
0108     //! a single type and the predicate to `find_if` must return a compile-time
0109     //! `Logical`, the `find_if` method is fairly useless. For similar reasons,
0110     //! the `find` method is also fairly useless. This model is provided mainly
0111     //! because of the `any_of` method & friends, which are both useful and
0112     //! compile-time efficient.
0113     //!
0114     //!
0115     //! Structure preserving functions
0116     //! ------------------------------
0117     //! Given two `Searchables` `S1` and `S2`, a function
0118     //! @f$ f : S_1(X) \to S_2(X) @f$ is said to preserve the `Searchable`
0119     //! structure if for all `xs` of data type `S1(X)` and predicates
0120     //! @f$ \mathtt{pred} : X \to Bool @f$ (for a `Logical` `Bool`),
0121     //! @code
0122     //!     any_of(xs, pred)  if and only if  any_of(f(xs), pred)
0123     //!     find_if(xs, pred) == find_if(f(xs), pred)
0124     //! @endcode
0125     //!
0126     //! This is really just a generalization of the following, more intuitive
0127     //! requirements. For all `xs` of data type `S1(X)` and `x` of data type
0128     //! `X`,
0129     //! @code
0130     //!     x ^in^ xs  if and only if  x ^in^ f(xs)
0131     //!     find(xs, x) == find(f(xs), x)
0132     //! @endcode
0133     //!
0134     //! These requirements can be understood as saying that `f` does not
0135     //! change the content of `xs`, although it may reorder elements.
0136     //! As usual, such a structure-preserving transformation is said to
0137     //! be an embedding if it is also injective, i.e. if it is a lossless
0138     //! transformation.
0139     template <typename S>
0140     struct Searchable;
0141 }} // end namespace boost::hana
0142 
0143 #endif // !BOOST_HANA_FWD_CONCEPT_SEARCHABLE_HPP