Remove unnecessary cross-references

This commit is contained in:
Christian Mazakas
2022-02-08 11:53:30 -08:00
parent 3800d712d5
commit 8d820ee7d0
7 changed files with 106 additions and 106 deletions

View File

@@ -22,7 +22,7 @@ public:
};
----
and you wish to use it as the key for an unordered_map. You need to customise the hash for this structure. To do this we need to combine the hash values for x and y. The function xref:#ref_hash_combine[boost::hash_combine] is supplied for this purpose:
and you wish to use it as the key for an unordered_map. You need to customise the hash for this structure. To do this we need to combine the hash values for x and y. The function `boost::hash_combine` is supplied for this purpose:
[listing,subs="+quotes,+macros"]
----
@@ -33,8 +33,8 @@ class point
friend std::size_t hash_value(point const& p)
{
std::size_t seed = 0;
xref:#ref_hash_combine[boost::hash_combine](seed, p.x);
xref:#ref_hash_combine[boost::hash_combine](seed, p.y);
boost::hash_combine(seed, p.x);
boost::hash_combine(seed, p.y);
return seed;
}
@@ -43,13 +43,13 @@ class point
};
----
Calls to `hash_combine` incrementally build the hash from the different members of `point`, it can be repeatedly called for any number of elements. It calls xref:#ref_hash_value[hash_value] on the supplied element, and combines it with the seed.
Calls to `hash_combine` incrementally build the hash from the different members of `point`, it can be repeatedly called for any number of elements. It calls `hash_value` on the supplied element, and combines it with the seed.
Full code for this example is at link:../../examples/point.cpp[/libs/container_hash/examples/point.cpp^].
[NOTE]
====
When using xref:#ref_hash_combine[boost::hash_combine] the order of the calls matters.
When using `boost::hash_combine` the order of the calls matters.
[listing,subs="+quotes,+macros"]
----
std::size_t seed = 0;
@@ -69,12 +69,12 @@ If you are calculating a hash value for data where the order of the data doesn't
====
To calculate the hash of an iterator range you can use xref:#ref_hash_range[boost::hash_range]:
To calculate the hash of an iterator range you can use `boost::hash_range`:
[listing,subs="+quotes,+macros"]
----
std::vector<std::string> some_strings;
std::size_t hash = xref:#ref_hash_range[boost::hash_range](some_strings.begin(), some_strings.end());
std::size_t hash = boost::hash_range(some_strings.begin(), some_strings.end());
----
Note that when writing template classes, you might not want to include the main hash header as it's quite an expensive include that brings in a lot of other headers, so instead you can include the `<boost/container_hash/hash_fwd.hpp>` header which forward declares xref:#ref_hash[boost::hash], xref:#ref_hash_range[boost::hash_range] and xref:#ref_hash_combine[boost::hash_combine]. You'll need to include the main header before instantiating xref:#ref_hash[boost::hash]. When using a container that uses xref:#ref_hash[boost::hash] it should do that for you, so your type will work fine with the boost hash containers. There's an example of this in link:../../examples/template.hpp[template.hpp^] and link:../../examples/template.cpp[template.cpp^].
Note that when writing template classes, you might not want to include the main hash header as it's quite an expensive include that brings in a lot of other headers, so instead you can include the `<boost/container_hash/hash_fwd.hpp>` header which forward declares `boost::hash`, `boost::hash_range` and `boost::hash_combine`. You'll need to include the main header before instantiating `boost::hash`. When using a container that uses `boost::hash` it should do that for you, so your type will work fine with the boost hash containers. There's an example of this in link:../../examples/template.hpp[template.hpp^] and link:../../examples/template.cpp[template.cpp^].

View File

@@ -3,7 +3,7 @@
:idprefix: custom_
xref:#ref_hash[boost::hash] is implemented by calling the function xref:#ref_hash_value[hash_value]. The namespace isn't specified so that it can detect overloads via argument dependant lookup. So if there is a free function `hash_value` in the same namespace as a custom type, it will get called.
`boost::hash` is implemented by calling the function `hash_value`. The namespace isn't specified so that it can detect overloads via argument dependant lookup. So if there is a free function `hash_value` in the same namespace as a custom type, it will get called.
If you have a structure `library::book`, where each book is uniquely defined by its member `id`:
@@ -35,13 +35,13 @@ namespace library
{
std::size_t hash_value(book const& b)
{
xref:#ref_hash[boost::hash]<int> hasher;
boost::hash<int> hasher;
return hasher(b.id);
}
}
----
And you can now use xref:#ref_hash[boost::hash] with book:
And you can now use `boost::hash` with book:
[listing,subs="+quotes,+macros"]
----
@@ -49,7 +49,7 @@ library::book knife(3458, "Zane Grey", "The Hash Knife Outfit");
library::book dandelion(1354, "Paul J. Shanley",
"Hash & Dandelion Greens");
xref:#ref_hash[boost::hash]<library::book> book_hasher;
boost::hash<library::book> book_hasher;
std::size_t knife_hash_value = book_hasher(knife);
// If std::unordered_set is available:

View File

@@ -3,7 +3,7 @@
:idprefix: disable_
While xref:#ref_hash[boost::hash]'s extensions are generally useful, you might want to turn them of in order to check that your code will work with other implementations of TR1. To do this define the macro `BOOST_HASH_NO_EXTENSIONS`. When this macro is defined, only the specialisations detailed in TR1 will be declared. But, if you later undefine the macro and include xref:#ref_header_boostcontainer_hashhash_hpp[<boost/container_hash/hash.hpp>] then the non-specialised form will be defined - activating the extensions.
While ``boost::hash``'s extensions are generally useful, you might want to turn them of in order to check that your code will work with other implementations of TR1. To do this define the macro `BOOST_HASH_NO_EXTENSIONS`. When this macro is defined, only the specialisations detailed in TR1 will be declared. But, if you later undefine the macro and include `<boost/container_hash/hash.hpp>` then the non-specialised form will be defined - activating the extensions.
It is strongly recommended that you never undefine the macro - and only define it so that it applies to the complete translation unit, either by defining it at the beginning of the main source file or, preferably, by using a compiler switch or preference. And you really should never define it in header files.

View File

@@ -3,7 +3,7 @@
:idprefix: intro_
xref:#ref_hash[boost::hash] is an implementation of the https://en.wikipedia.org/wiki/Hash_function[hash function^] object specified by the http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf[Draft Technical Report on C++ Library Extensions^] (TR1). It is the default hash function for link:../../../unordered/index.html[Boost.Unordered^], link:../../../intrusive/index.html[Boost.Intrusive^]'s unordered associative containers, and link:../../../multi_index/index.html[Boost.MultiIndex^]'s hash indicies and link:../../../bimap/index.html[Boost.Bimap^]'s `unordered_set_of`.
`boost::hash` is an implementation of the https://en.wikipedia.org/wiki/Hash_function[hash function^] object specified by the http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf[Draft Technical Report on C++ Library Extensions^] (TR1). It is the default hash function for link:../../../unordered/index.html[Boost.Unordered^], link:../../../intrusive/index.html[Boost.Intrusive^]'s unordered associative containers, and link:../../../multi_index/index.html[Boost.MultiIndex^]'s hash indicies and link:../../../bimap/index.html[Boost.Bimap^]'s `unordered_set_of`.
As it is compliant with http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf[TR1^], it will work with:
@@ -17,6 +17,6 @@ It also implements the extension proposed by Peter Dimov in issue 6.18 of the ht
* arrays
* `std::pair`
* the standard containers.
* extending xref:#ref_hash[boost::hash] for custom types.
* extending `boost::hash` for custom types.
NOTE: This hash function is designed to be used in containers based on the STL and is not suitable as a general purpose hash function. For more details see the <<rationale,rationale>>.

View File

@@ -3,9 +3,9 @@
:idprefix: portability_
xref:#ref_hash[boost::hash] is written to be as portable as possible, but unfortunately, several older compilers don't support argument dependent lookup (ADL) - the mechanism used for customisation. On those compilers custom overloads for `hash_value` needs to be declared in the `boost` namespace.
`boost::hash` is written to be as portable as possible, but unfortunately, several older compilers don't support argument dependent lookup (ADL) - the mechanism used for customisation. On those compilers custom overloads for `hash_value` needs to be declared in the `boost` namespace.
On a strictly standards compliant compiler, an overload defined in the `boost` namespace won't be found when xref:#ref_hash[boost::hash] is instantiated, so for these compilers the overload should only be declared in the same namespace as the class.
On a strictly standards compliant compiler, an overload defined in the `boost` namespace won't be found when `boost::hash` is instantiated, so for these compilers the overload should only be declared in the same namespace as the class.
Let's say we have a simple custom type:
@@ -22,7 +22,7 @@ namespace foo
friend std::size_t hash_value(custom_type x)
{
xref:#ref_hash[boost::hash]<int> hasher;
boost::hash<int> hasher;
return hasher(x.value);
}
};
@@ -46,7 +46,7 @@ namespace foo
std::size_t hash(custom_type x)
{
xref:#ref_hash[boost::hash]<T> hasher;
boost::hash<T> hasher;
return hasher(value);
}
};

View File

@@ -7,113 +7,113 @@ For the full specification, see section 6.3 of the http://www.open-std.org/jtc1/
== Header <boost/container_hash/hash.hpp>
Defines xref:#ref_hash[boost::hash], and helper functions.
Defines `boost::hash`, and helper functions.
[listing,subs="+quotes,+macros"]
----
namespace boost {
template<typename T> struct xref:#ref_hash[hash];
template<typename T> struct hash;
template<> struct xref:#ref_specializations[hash]<bool>;
template<> struct xref:#ref_specializations[hash]<char>;
template<> struct xref:#ref_specializations[hash]<signed char>;
template<> struct xref:#ref_specializations[hash]<unsigned char>;
template<> struct xref:#ref_specializations[hash]<wchar_t>;
template<> struct xref:#ref_specializations[hash]<char16_t>;
template<> struct xref:#ref_specializations[hash]<char32_t>;
template<> struct xref:#ref_specializations[hash]<short>;
template<> struct xref:#ref_specializations[hash]<unsigned short>;
template<> struct xref:#ref_specializations[hash]<int>;
template<> struct xref:#ref_specializations[hash]<unsigned int>;
template<> struct xref:#ref_specializations[hash]<long>;
template<> struct xref:#ref_specializations[hash]<unsigned long>;
template<> struct xref:#ref_specializations[hash]<long long>;
template<> struct xref:#ref_specializations[hash]<unsigned long long>;
template<> struct xref:#ref_specializations[hash]<float>;
template<> struct xref:#ref_specializations[hash]<double>;
template<> struct xref:#ref_specializations[hash]<long double>;
template<> struct xref:#ref_specializations[hash]<std::string>;
template<> struct xref:#ref_specializations[hash]<std::wstring>;
template<> struct xref:#ref_specializations[hash]<std::u16string>;
template<> struct xref:#ref_specializations[hash]<std::u32string>;
template<> struct xref:#ref_specializations[hash]<std::type_index>;
template<> struct hash<bool>;
template<> struct hash<char>;
template<> struct hash<signed char>;
template<> struct hash<unsigned char>;
template<> struct hash<wchar_t>;
template<> struct hash<char16_t>;
template<> struct hash<char32_t>;
template<> struct hash<short>;
template<> struct hash<unsigned short>;
template<> struct hash<int>;
template<> struct hash<unsigned int>;
template<> struct hash<long>;
template<> struct hash<unsigned long>;
template<> struct hash<long long>;
template<> struct hash<unsigned long long>;
template<> struct hash<float>;
template<> struct hash<double>;
template<> struct hash<long double>;
template<> struct hash<std::string>;
template<> struct hash<std::wstring>;
template<> struct hash<std::u16string>;
template<> struct hash<std::u32string>;
template<> struct hash<std::type_index>;
template<typename T> struct xref:#ref_specializations[hash]<T*>;
template<typename T> struct hash<T*>;
// xref:#ref_support_functions_boost_extension[Support functions (Boost extension).]
// Support functions (Boost extension).
template<typename T>
void xref:#ref_hash_combine[hash_combine](size_t &, T const&);
void hash_combine(size_t &, T const&);
template<typename It>
std::size_t xref:#ref_hash_range[hash_range](It, It);
std::size_t hash_range(It, It);
template<typename It>
void xref:#ref_hash_range[hash_range](std::size_t&, It, It);
void hash_range(std::size_t&, It, It);
// xref:#ref_overloadable_hash_implementation_boost_extension[Overloadable hash implementation (Boost extension).]
std::size_t xref:#ref_hash_value[hash_value](bool);
std::size_t xref:#ref_hash_value[hash_value](char);
std::size_t xref:#ref_hash_value[hash_value](signed char);
std::size_t xref:#ref_hash_value[hash_value](unsigned char);
std::size_t xref:#ref_hash_value[hash_value](wchar_t);
std::size_t xref:#ref_hash_value[hash_value](char16_t);
std::size_t xref:#ref_hash_value[hash_value](char32_t);
std::size_t xref:#ref_hash_value[hash_value](short);
std::size_t xref:#ref_hash_value[hash_value](unsigned short);
std::size_t xref:#ref_hash_value[hash_value](int);
std::size_t xref:#ref_hash_value[hash_value](unsigned int);
std::size_t xref:#ref_hash_value[hash_value](long);
std::size_t xref:#ref_hash_value[hash_value](unsigned long);
std::size_t xref:#ref_hash_value[hash_value](long long);
std::size_t xref:#ref_hash_value[hash_value](unsigned long long);
std::size_t xref:#ref_hash_value[hash_value](float);
std::size_t xref:#ref_hash_value[hash_value](double);
std::size_t xref:#ref_hash_value[hash_value](long double);
// Overloadable hash implementation (Boost extension).
std::size_t hash_value(bool);
std::size_t hash_value(char);
std::size_t hash_value(signed char);
std::size_t hash_value(unsigned char);
std::size_t hash_value(wchar_t);
std::size_t hash_value(char16_t);
std::size_t hash_value(char32_t);
std::size_t hash_value(short);
std::size_t hash_value(unsigned short);
std::size_t hash_value(int);
std::size_t hash_value(unsigned int);
std::size_t hash_value(long);
std::size_t hash_value(unsigned long);
std::size_t hash_value(long long);
std::size_t hash_value(unsigned long long);
std::size_t hash_value(float);
std::size_t hash_value(double);
std::size_t hash_value(long double);
template<typename T>
std::size_t xref:#ref_hash_value[hash_value](T* const&);
std::size_t hash_value(T* const&);
template<typename T, unsigned N>
std::size_t xref:#ref_hash_value[hash_value](T (&val)[N]);
std::size_t hash_value(T (&val)[N]);
template<typename T, unsigned N>
std::size_t xref:#ref_hash_value[hash_value](const T (&val)[N]);
std::size_t hash_value(const T (&val)[N]);
template<typename Ch, typename A>
std::size_t xref:#ref_hash_value[hash_value](std::basic_string<Ch, std::char_traits<Ch>, A> const&);
std::size_t hash_value(std::basic_string<Ch, std::char_traits<Ch>, A> const&);
template<typename A, typename B>
std::size_t xref:#ref_hash_value[hash_value](std::pair<A, B> const&);
std::size_t hash_value(std::pair<A, B> const&);
template<typename T, typename A>
std::size_t xref:#ref_hash_value[hash_value](std::vector<T, A> const&);
std::size_t hash_value(std::vector<T, A> const&);
template<typename T, typename A>
std::size_t xref:#ref_hash_value[hash_value](std::list<T, A> const&);
std::size_t hash_value(std::list<T, A> const&);
template<typename T, typename A>
std::size_t xref:#ref_hash_value[hash_value](std::deque<T, A> const&);
std::size_t hash_value(std::deque<T, A> const&);
template<typename K, typename C, typename A>
std::size_t xref:#ref_hash_value[hash_value](std::set<K, C, A> const&);
std::size_t hash_value(std::set<K, C, A> const&);
template<typename K, typename C, typename A>
std::size_t xref:#ref_hash_value[hash_value](std::multiset<K, C, A> const&);
std::size_t hash_value(std::multiset<K, C, A> const&);
template<typename K, typename T, typename C, typename A>
std::size_t xref:#ref_hash_value[hash_value](std::map<K, T, C, A> const&);
std::size_t hash_value(std::map<K, T, C, A> const&);
template<typename K, typename T, typename C, typename A>
std::size_t xref:#ref_hash_value[hash_value](std::multimap<K, T, C, A> const&);
std::size_t hash_value(std::multimap<K, T, C, A> const&);
template<typename T> std::size_t xref:#ref_hash_value[hash_value](std::complex<T> const&);
std::size_t xref:#ref_hash_value[hash_value](std::type_index);
template<typename T> std::size_t hash_value(std::complex<T> const&);
std::size_t hash_value(std::type_index);
template<typename T, std::size_t N>
std::size_t xref:#ref_hash_value[hash_value](std::array<T, N> const&);
std::size_t hash_value(std::array<T, N> const&);
template<typename... T>
std::size_t xref:#ref_hash_value[hash_value](std::tuple<T...>);
std::size_t hash_value(std::tuple<T...>);
}
----
@@ -127,7 +127,7 @@ namespace boost {
[listing,subs="+quotes,+macros"]
----
// xref:#ref_header_boostcontainer_hashhash_hpp[#include <boost/container_hash/hash.hpp>]
// #include <boost/container_hash/hash.hpp>
template<typename T>
struct hash : public std::unary_function<T, std::size_t> {
@@ -143,9 +143,9 @@ std::size_t operator()(T const& val) const;
----
[horizontal]
Returns:: xref:#ref_hash_value[hash_value](val)
Returns:: `hash_value(val)`
Notes:: The call to xref:#ref_hash_value[hash_value] is unqualified, so that custom overloads can be found via argument dependent lookup.
Notes:: The call to `hash_value` is unqualified, so that custom overloads can be found via argument dependent lookup.
+
This is not defined when the macro `BOOST_HASH_NO_EXTENSIONS` is defined. The specializations are still defined, so only the specializations required by TR1 are defined.
+
@@ -153,7 +153,7 @@ Forward declared in `<boost/container_hash/hash_fwd.hpp>`
+
This hash function is not intended for general use, and isn't guaranteed to be equal during separate runs of a program - so please don't use it for any persistent storage or communication.
Throws:: Only throws if xref:#ref_hash_value[hash_value](T) throws.
Throws:: Only throws if `hash_value(T)` throws.
== Specializations
@@ -180,7 +180,7 @@ std::size_t operator()(T const val) const;
[horizontal]
Returns:: Unspecified in TR1, except that equal arguments yield the same result.
+
xref:#ref_hash_value[hash_value](val) in Boost.
`hash_value(val)` in Boost.
[horizontal]
Throws:: Doesn't throw
@@ -198,10 +198,10 @@ void hash_combine(size_t &, T const&);
Called repeatedly to incrementally create a hash value from several variables.
[horizontal]
Effects:: Updates seed with a new hash value generated by combining it with the result of xref:#ref_hash_value[hash_value](v). Will always produce the same result for the same combination of seed and xref:#ref_hash_value[hash_value](v) during the single run of a program.
Effects:: Updates seed with a new hash value generated by combining it with the result of `hash_value(v)`. Will always produce the same result for the same combination of seed and `hash_value(v)` during the single run of a program.
[horizontal]
Notes:: xref:#ref_hash_value[hash_value] is called without qualification, so that overloads can be found via ADL. +
Notes:: `hash_value` is called without qualification, so that overloads can be found via ADL. +
+
This is an extension to TR1 +
+
@@ -210,7 +210,7 @@ Forward declared in `<boost/container_hash/hash_fwd.hpp>` +
This hash function is not intended for general use, and isn't guaranteed to be equal during separate runs of a program - so please don't use it for any persistent storage or communication.
[horizontal]
Throws:: Only throws if xref:#ref_hash_value[hash_value](T) throws. Strong exception safety, as long as xref:#ref_hash_value[hash_value](T) also has strong exception safety.
Throws:: Only throws if `hash_value(T)` throws. Strong exception safety, as long as `hash_value(T)` also has strong exception safety.
=== hash_range
@@ -234,7 +234,7 @@ size_t seed = 0;
for(; first != last; ++first)
{
xref:#ref_hash_combine[hash_combine](seed, *first);
hash_combine(seed, *first);
}
return seed;
----
@@ -245,7 +245,7 @@ For the three arguments overload:
----
for(; first != last; ++first)
{
xref:#ref_hash_combine[hash_combine](seed, *first);
hash_combine(seed, *first);
}
----
@@ -259,7 +259,7 @@ Forward declared in `<boost/container_hash/hash_fwd.hpp>`
This hash function is not intended for general use, and isn't guaranteed to be equal during separate runs of a program - so please don't use it for any persistent storage or communication.
[horizontal]
Throws:: Only throws if xref:#ref_hash_value[hash_value]`(std::iterator_traits<It>::value_type)` throws. `hash_range(std::size_t&, It, It)` has basic exception safety as long as xref:#ref_hash_value[hash_value]`(std::iterator_traits<It>::value_type)` has basic exception safety.
Throws:: Only throws if `hash_value(std::iterator_traits<It>::value_type)` throws. `hash_range(std::size_t&, It, It)` has basic exception safety as long as `hash_value(std::iterator_traits<It>::value_type)` has basic exception safety.
== Overloadable hash implementation (Boost extension).
@@ -319,7 +319,7 @@ template<typename... T>
Implementation of the hash function.
Generally shouldn't be called directly by users, instead they should use xref:#ref_hash[boost::hash], xref:#ref_hash_range[boost::hash_range] or xref:#ref_hash_combine[boost::hash_combine] which call `hash_value` without namespace qualification so that overloads for custom types are found via ADL.
Generally shouldn't be called directly by users, instead they should use `boost::hash`, `boost::hash_range` or `boost::hash_combine` which call `hash_value` without namespace qualification so that overloads for custom types are found via ADL.
[horizontal]
Notes:: This is an extension to TR1
@@ -327,7 +327,7 @@ Notes:: This is an extension to TR1
This hash function is not intended for general use, and isn't guaranteed to be equal during separate runs of a program - so please don't use it for any persistent storage or communication.
[horizontal]
Throws:: Only throws if a user supplied version of xref:#ref_hash_value[hash_value] throws for an element of a container, or one of the types stored in a pair.
Throws:: Only throws if a user supplied version of `hash_value` throws for an element of a container, or one of the types stored in a pair.
[vertical]
Returns::

View File

@@ -3,30 +3,30 @@
:idprefix: tutorial_
When using a hash index with link:../../../multi_index/index.html[Boost.MultiIndex^], you don't need to do anything to use xref:#ref_hash[boost::hash] as it uses it by default. To find out how to use a user-defined type, read the <<custom,section on extending boost::hash for a custom data type>>.
When using a hash index with link:../../../multi_index/index.html[Boost.MultiIndex^], you don't need to do anything to use `boost::hash` as it uses it by default. To find out how to use a user-defined type, read the <<custom,section on extending boost::hash for a custom data type>>.
If your standard library supplies its own implementation of the unordered associative containers and you wish to use xref:#ref_hash[boost::hash], just use an extra template parameter:
If your standard library supplies its own implementation of the unordered associative containers and you wish to use `boost::hash`, just use an extra template parameter:
[listing,subs="+quotes,+macros"]
----
std::unordered_multiset<int, xref:#ref_hash[boost::hash]<int> >
std::unordered_multiset<int, boost::hash<int> >
set_of_ints;
std::unordered_set<std::pair<int, int>, xref:#ref_hash[boost::hash]<std::pair<int, int> > >
std::unordered_set<std::pair<int, int>, boost::hash<std::pair<int, int> > >
set_of_pairs;
std::unordered_map<int, std::string, xref:#ref_hash[boost::hash]<int> > map_int_to_string;
std::unordered_map<int, std::string, boost::hash<int> > map_int_to_string;
----
To use xref:#ref_hash[boost::hash] directly, create an instance and call it as a function:
To use `boost::hash` directly, create an instance and call it as a function:
[listing,subs="+quotes,+macros"]
----
xref:#ref_header_boostcontainer_hashhash_hpp[++#include <boost/container_hash/hash.hpp>++]
#include <boost/container_hash/hash.hpp>
int main()
{
xref:#ref_hash[boost::hash]<std::string> string_hash;
boost::hash<std::string> string_hash;
std::size_t h = string_hash("Hash me");
}
@@ -41,7 +41,7 @@ std::vector<std::size_t> get_hashes(Container const& x)
{
std::vector<std::size_t> hashes;
std::transform(x.begin(), x.end(), std::back_inserter(hashes),
xref:#ref_hash[boost::hash]<typename Container::value_type>());
boost::hash<typename Container::value_type>());
return hashes;
}