|
||||
File indexing completed on 2025-01-18 09:37:58
0001 /*! 0002 @file 0003 Forward declares `boost::hana::Struct`. 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_STRUCT_HPP 0011 #define BOOST_HANA_FWD_CONCEPT_STRUCT_HPP 0012 0013 #include <boost/hana/config.hpp> 0014 0015 0016 namespace boost { namespace hana { 0017 //! @ingroup group-concepts 0018 //! @defgroup group-Struct Struct 0019 //! The `Struct` concept represents `struct`-like user-defined types. 0020 //! 0021 //! The `Struct` concept allows restricted compile-time reflection over 0022 //! user-defined types. In particular, it allows accessing the names of 0023 //! the members of a user-defined type, and also the value of those 0024 //! members. `Struct`s can also be folded, searched and converted to 0025 //! some types of containers, where more advanced transformations can 0026 //! be performed. 0027 //! 0028 //! While all types can _in theory_ be made `Struct`s, only a subset of 0029 //! them are actually interesting to see as such. More precisely, it is 0030 //! only interesting to make a type a `Struct` when it is conceptually 0031 //! a C++ `struct`, i.e. a mostly dumb aggregate of named data. The way 0032 //! this data is accessed is mostly unimportant to the `Struct` concept; 0033 //! it could be through getters and setters, through public members, 0034 //! through non-member functions or it could even be generated on-the-fly. 0035 //! The important part, which is made precise below, is that those accessor 0036 //! methods should be move-independent. 0037 //! 0038 //! Another way to see a `Struct` is as a map where the keys are the names 0039 //! of the members and the values are the values of those members. However, 0040 //! there are subtle differences like the fact that one can't add a member 0041 //! to a `Struct`, and also that the order of the members inside a `Struct` 0042 //! plays a role in determining the equality of `Struct`s, which is not 0043 //! the case for maps. 0044 //! 0045 //! 0046 //! Minimal complete definition 0047 //! --------------------------- 0048 //! `accessors` 0049 //! 0050 //! A model of `Struct` is created by specifying a sequence of key/value 0051 //! pairs with the `accessors` function. The first element of a pair in 0052 //! this sequence represents the "name" of a member of the `Struct`, while 0053 //! the second element is a function which retrieves this member from an 0054 //! object. The "names" do not have to be in any special form; they just 0055 //! have to be compile-time `Comparable`. For example, it is common to 0056 //! provide "names" that are `hana::string`s representing the actual names 0057 //! of the members, but one could provide `hana::integral_constant`s just 0058 //! as well. The values must be functions which, when given an object, 0059 //! retrieve the appropriate member from it. 0060 //! 0061 //! There are several ways of providing the `accessors` method, some of 0062 //! which are more flexible and others which are more convenient. First, 0063 //! one can define it through tag-dispatching, as usual. 0064 //! @snippet example/struct.mcd.tag_dispatching.cpp main 0065 //! 0066 //! Secondly, it is possible to provide a nested `hana_accessors_impl` 0067 //! type, which should be equivalent to a specialization of 0068 //! `accessors_impl` for tag-dispatching. However, for a type `S`, this 0069 //! technique only works when the data type of `S` is `S` itself, which 0070 //! is the case unless you explicitly asked for something else. 0071 //! @snippet example/struct.mcd.nested.cpp main 0072 //! 0073 //! Finally, the most convenient (but least flexible) option is to use 0074 //! the `BOOST_HANA_DEFINE_STRUCT`, the `BOOST_HANA_ADAPT_STRUCT` or the 0075 //! `BOOST_HANA_ADAPT_ADT` macro, which provide a minimal syntactic 0076 //! overhead. See the documentation of these macros for details on how 0077 //! to use them. 0078 //! 0079 //! Also note that it is not important that the accessor functions retrieve 0080 //! an actual member of the struct (e.g. `x.member`). Indeed, an accessor 0081 //! function could call a custom getter or even compute the value of the 0082 //! member on the fly: 0083 //! @snippet example/struct.custom_accessor.cpp main 0084 //! 0085 //! The only important thing is that the accessor functions are 0086 //! move-independent, a notion which is defined below. 0087 //! 0088 //! 0089 //! @anchor move-independence 0090 //! Move-independence 0091 //! ----------------- 0092 //! The notion of move-independence presented here defines rigorously 0093 //! when it is legitimate to "double-move" from an object. 0094 //! 0095 //! A collection of functions `f1, ..., fn` sharing the same domain is 0096 //! said to be _move-independent_ if for every fresh (not moved-from) 0097 //! object `x` in the domain, any permutation of the following statements 0098 //! is valid and leaves the `zk` objects in a fresh (not moved-from) state: 0099 //! @code 0100 //! auto z1 = f1(std::move(x)); 0101 //! ... 0102 //! auto zn = fn(std::move(x)); 0103 //! @endcode 0104 //! 0105 //! @note 0106 //! In the special case where some functions return objects that can't be 0107 //! bound to with `auto zk =` (like `void` or a non-movable, non-copyable 0108 //! type), just pretend the return value is ignored. 0109 //! 0110 //! Intuitively, this ensures that we can treat `f1, ..., fn` as 0111 //! "accessors" that decompose `x` into independent subobjects, and 0112 //! that do so without moving from `x` more than that subobject. This 0113 //! is important because it allows us to optimally decompose `Struct`s 0114 //! into their subparts inside the library. 0115 //! 0116 //! 0117 //! Laws 0118 //! ---- 0119 //! For any `Struct` `S`, the accessors in the `accessors<S>()` sequence 0120 //! must be move-independent, as defined above. 0121 //! 0122 //! 0123 //! Refined concepts 0124 //! ---------------- 0125 //! 1. `Comparable` (free model)\n 0126 //! `Struct`s are required to be `Comparable`. Specifically, two `Struct`s 0127 //! of the same data type `S` must be equal if and only if all of their 0128 //! members are equal. By default, a model of `Comparable` doing just that 0129 //! is provided for models of `Struct`. In particular, note that the 0130 //! comparison of the members is made in the same order as they appear in 0131 //! the `hana::members` sequence. 0132 //! @include example/struct/comparable.cpp 0133 //! 0134 //! 2. `Foldable` (free model)\n 0135 //! A `Struct` can be folded by considering it as a list of pairs each 0136 //! containing the name of a member and the value associated to that 0137 //! member, in the same order as they appear in the `hana::members` 0138 //! sequence. By default, a model of `Foldable` doing just that is 0139 //! provided for models of the `Struct` concept. 0140 //! @include example/struct/foldable.cpp 0141 //! Being a model of `Foldable` makes it possible to turn a `Struct` 0142 //! into basically any `Sequence`, but also into a `hana::map` by simply 0143 //! using the `to<...>` function! 0144 //! @include example/struct/to.cpp 0145 //! 0146 //! 3. `Searchable` (free model)\n 0147 //! A `Struct` can be searched by considering it as a map where the keys 0148 //! are the names of the members of the `Struct`, and the values are the 0149 //! members associated to those names. By default, a model of `Searchable` 0150 //! is provided for any model of the `Struct` concept. 0151 //! @include example/struct/searchable.cpp 0152 template <typename S> 0153 struct Struct; 0154 }} // end namespace boost::hana 0155 0156 #endif // !BOOST_HANA_FWD_CONCEPT_STRUCT_HPP
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |