forked from boostorg/container_hash
Remove unneeded QuickBook and sample files from docs
This commit is contained in:
222
doc/changes.qbk
222
doc/changes.qbk
@@ -1,222 +0,0 @@
|
||||
|
||||
[/ Copyright 2005-2008 Daniel James.
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[template ticket[number]'''<ulink url="https://svn.boost.org/trac/boost/ticket/'''[number]'''">'''#[number]'''</ulink>''']
|
||||
|
||||
[section:changes Change Log]
|
||||
|
||||
[h2 Boost 1.33.0]
|
||||
|
||||
* Initial Release
|
||||
|
||||
[h2 Boost 1.33.1]
|
||||
|
||||
* Fixed the points example, as pointed out by 沈慧峰.
|
||||
|
||||
[h2 Boost 1.34.0]
|
||||
|
||||
* Use declarations for standard classes, so that the library
|
||||
doesn't need to include all of their headers
|
||||
* Deprecated the `<boost/functional/hash/*.hpp>` headers. Now a single header,
|
||||
<[headerref boost/functional/hash.hpp]> is used.
|
||||
* Add support for the `BOOST_HASH_NO_EXTENSIONS` macro, which
|
||||
disables the extensions to TR1.
|
||||
|
||||
* Minor improvements to the hash functions for floating point numbers.
|
||||
* Update the portable example to hopefully be more generally portable.
|
||||
|
||||
[h2 Boost 1.34.1]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/952 Ticket 952]:
|
||||
Suppress incorrect 64-bit warning on Visual C++.
|
||||
|
||||
[h2 Boost 1.35.0]
|
||||
|
||||
* Support for `long long`, `std::complex`.
|
||||
* Improved algorithm for hashing floating point numbers:
|
||||
* Improved portablity, as described by Daniel Krügler in
|
||||
[@http://lists.boost.org/boost-users/2005/08/13418.php
|
||||
a post to the boost users list].
|
||||
* Fits more information into each combine loop, which can reduce the
|
||||
the number of times combine is called and hopefully give a better
|
||||
quality hash function.
|
||||
* Improved the algorithm for hashing floating point numbers.
|
||||
* On Cygwin use a binary hash function for floating point numbers, as
|
||||
Cygwin doesn't have decent floating point functions for `long double`.
|
||||
* Never uses `fpclass` which doesn't support `long double`.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/1064 Ticket 1064]:
|
||||
Removed unnecessary use of `errno`.
|
||||
* Explicitly overload for more built in types.
|
||||
* Minor improvements to the documentation.
|
||||
* A few bug and warning fixes:
|
||||
* [@http://svn.boost.org/trac/boost/ticket/1509 Ticket 1509]:
|
||||
Suppress another Visual C++ warning.
|
||||
* Some workarounds for the Sun compilers.
|
||||
|
||||
[h2 Boost 1.36.0]
|
||||
|
||||
* Stop using OpenBSD's dodgy `std::numeric_limits`.
|
||||
* Using the boost typedefs for `long long` and `unsigned long long`.
|
||||
* Move the extensions into their own header.
|
||||
|
||||
[h2 Boost 1.37.0]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/2264 Ticket 2264]:
|
||||
In Visual C++, always use C99 float functions for `long double` and `float` as
|
||||
the C++ overloads aren't always availables.
|
||||
|
||||
[h2 Boost 1.38.0]
|
||||
|
||||
* Changed the warnings in the deprecated headers from 1.34.0 to errors. These
|
||||
will be removed in a future version of Boost.
|
||||
* Moved detail headers out of `boost/container_hash/detail`, since they are part of
|
||||
functional/hash, not container_hash. `boost/container_hash/detail/container_fwd.hpp`
|
||||
has been moved to `boost/detail/container_fwd.hpp` as it's used outside of
|
||||
this library, the others have been moved to `boost/functional/hash/detail`.
|
||||
|
||||
[h2 Boost 1.39.0]
|
||||
|
||||
* Move the hash_fwd.hpp implementation into the hash subdirectory, leaving a
|
||||
forwarding header in the old location. You should still use the old location,
|
||||
the new location is mainly for implementation and possible modularization.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/2412 Ticket 2412]: Removed deprecated
|
||||
headers.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/2957 Ticket 2957]: Fix configuration
|
||||
for vxworks.
|
||||
|
||||
[h2 Boost 1.40.0]
|
||||
|
||||
* Automatically configure the float functions using template metaprogramming
|
||||
instead of trying to configure every possibility manually.
|
||||
* Workaround for when STLport doesn't support long double.
|
||||
|
||||
[h2 Boost 1.42.0]
|
||||
|
||||
* Reduce the number of warnings for Visual C++ warning level 4.
|
||||
* Some code formatting changes to fit lines into 80 characters.
|
||||
* Rename an internal namespace.
|
||||
|
||||
[h2 Boost 1.43.0]
|
||||
|
||||
* [@https://svn.boost.org/trac/boost/ticket/3866 Ticket 3866]:
|
||||
Don't foward declare containers when using gcc's parallel library,
|
||||
allow user to stop forward declaration by defining the
|
||||
`BOOST_DETAIL_NO_CONTAINER_FWD` macro.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/4038 Ticket 4038]:
|
||||
Avoid hashing 0.5 and 0 to the same number.
|
||||
* Stop using deprecated `BOOST_HAS_*` macros.
|
||||
|
||||
[h2 Boost 1.44.0]
|
||||
|
||||
* Add option to prevent implicit conversions when calling `hash_value` by
|
||||
defining `BOOST_HASH_NO_IMPLICIT_CASTS`. When using `boost::hash`
|
||||
for a type that does not have `hash_value` declared but does have
|
||||
an implicit conversion to a type that does, it would use that
|
||||
implicit conversion to hash it. Which can sometimes go very wrong,
|
||||
e.g. using a conversion to bool and only hashing to 2 possible
|
||||
values. Since fixing this is a breaking change and was only
|
||||
approached quite late in the release cycle with little discussion
|
||||
it's opt-in for now. This, or something like it, will become the
|
||||
default in a future version.
|
||||
|
||||
[h2 Boost 1.46.0]
|
||||
|
||||
* Avoid warning due with gcc's `-Wconversion` flag.
|
||||
|
||||
[h2 Boost 1.50.0]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/6771 Ticket 6771]:
|
||||
Avoid gcc's `-Wfloat-equal` warning.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/6806 Ticket 6806]:
|
||||
Support `std::array` and `std::tuple` when available.
|
||||
* Add deprecation warning to the long deprecated
|
||||
`boost/container_hash/detail/container_fwd.hpp`.
|
||||
|
||||
[h2 Boost 1.51.0]
|
||||
|
||||
* Support the standard smart pointers.
|
||||
* `hash_value` now implemented using SFINAE to avoid implicit casts to built
|
||||
in types when calling it.
|
||||
* Updated to use the new config macros.
|
||||
|
||||
[h2 Boost 1.52.0]
|
||||
|
||||
* Restore `enum` support, which was accidentally removed in the last version.
|
||||
* New floating point hasher - will hash the binary representation on more
|
||||
platforms, which should be faster.
|
||||
|
||||
[h2 Boost 1.53.0]
|
||||
|
||||
* Add support for `boost::int128_type` and `boost::uint128_type` where
|
||||
available - currently only `__int128` and `unsigned __int128` on some
|
||||
versions of gcc.
|
||||
* On platforms that are known to have the standard floating point functions,
|
||||
don't use automatic detection - which can break if there are ambiguous
|
||||
overloads.
|
||||
* Fix undefined behaviour when using the binary float hash (Thomas Heller).
|
||||
|
||||
[h2 Boost 1.54.0]
|
||||
|
||||
* [@https://svn.boost.org/trac/boost/ticket/7957 Ticket 7957]:
|
||||
Fixed a typo.
|
||||
|
||||
[h2 Boost 1.55.0]
|
||||
|
||||
* Simplify a SFINAE check so that it will hopefully work on Sun 5.9
|
||||
([ticket 8822]).
|
||||
* Suppress Visual C++ infinite loop warning ([ticket 8568]).
|
||||
|
||||
[h2 Boost 1.56.0]
|
||||
|
||||
* Removed some Visual C++ 6 workarounds.
|
||||
* Ongoing work on improving `hash_combine`. This changes the combine function
|
||||
which was previously defined in the reference documentation.
|
||||
|
||||
[h2 Boost 1.58.0]
|
||||
|
||||
* Fixed strict aliasing violation
|
||||
([@https://github.com/boostorg/container_hash/pull/3 GitHub #3]).
|
||||
|
||||
[h2 Boost 1.63.0]
|
||||
|
||||
* Fixed some warnings.
|
||||
* Only define hash for `std::wstring` when we know we have a `wchar_t`.
|
||||
Otherwise there's a compile error as there's no overload for hashing
|
||||
the characters in wide strings ([ticket 8552]).
|
||||
|
||||
[h2 Boost 1.64.0]
|
||||
|
||||
* Fix for recent versions of Visual C++ which have removed `std::unary_function`
|
||||
and `std::binary_function` ([ticket 12353]).
|
||||
|
||||
[h2 Boost 1.65.0]
|
||||
|
||||
* Support for `char16_t`, `char32_t`, `u16string`, `u32string`
|
||||
|
||||
[h2 Boost 1.66.0]
|
||||
|
||||
* Avoid float comparison warning when using Clang - this workaround was
|
||||
already in place for GCC, and was used when Clang pretends to be GCC,
|
||||
but the warning was appearing when running Clang in other contexts.
|
||||
|
||||
[h2 Boost 1.67.0]
|
||||
|
||||
* Moved library into its own module, `container_hash`.
|
||||
* Moved headers for new module name, now at:
|
||||
`<boost/container_hash/hash.hpp>`,
|
||||
`<boost/container_hash/hash_fwd.hpp>`,
|
||||
`<boost/container_hash/extensions.hpp>`.
|
||||
* Added forwarding headers to support the old headers locations.
|
||||
* Support `std::string_view`, `std::error_code`, `std::error_condition`
|
||||
`std::optional`, `std::variant`, `std::monostate` where available.
|
||||
* Update include paths from other Boost libraries.
|
||||
* Manually write out tuple overloads, rather than using the
|
||||
preprocessor to generate them. Should improve usability, due
|
||||
to better error messages, and easier debugging.
|
||||
* Fix tutorial example ([ticket 11017]).
|
||||
* Quick fix for hashing `vector<bool>` when using libc++. Will try to introduce
|
||||
a more general fix in the next release.
|
||||
|
||||
[endsect]
|
@@ -1,29 +0,0 @@
|
||||
|
||||
[/ Copyright 2005-2008 Daniel James.
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[section:disable Disabling The Extensions]
|
||||
|
||||
While [classref 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
|
||||
<[headerref 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.
|
||||
|
||||
If you are writing a library which has code in the header which requires the
|
||||
extensions, then the best action is to tell users not to define the macro.
|
||||
Their code won't ['require] the macro.
|
||||
|
||||
Translation units that are compiled with the macro defined will link with units
|
||||
that were compiled without it. This feature has been designed to avoid ODR
|
||||
violations.
|
||||
|
||||
[endsect]
|
29
doc/hash.qbk
29
doc/hash.qbk
@@ -1,29 +0,0 @@
|
||||
[library Boost.ContainerHash
|
||||
[quickbook 1.5]
|
||||
[authors [James, Daniel]]
|
||||
[copyright 2005 2006 2007 2008 Daniel James]
|
||||
[purpose A TR1 hash function object that can be extended to hash user
|
||||
defined types]
|
||||
[category higher-order]
|
||||
[id hash]
|
||||
[dirname container_hash]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
||||
]
|
||||
]
|
||||
|
||||
[def __issues__
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf
|
||||
Library Extension Technical Report Issues List]]
|
||||
|
||||
[include:hash intro.qbk]
|
||||
[include:hash tutorial.qbk]
|
||||
[include:hash portability.qbk]
|
||||
[include:hash disable.qbk]
|
||||
[include:hash changes.qbk]
|
||||
[include:hash rationale.qbk]
|
||||
[xinclude ref.xml]
|
||||
[include:hash links.qbk]
|
||||
[include:hash thanks.qbk]
|
@@ -1,52 +0,0 @@
|
||||
|
||||
[/ Copyright 2005-2008 Daniel James.
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[section:intro Introduction]
|
||||
|
||||
[def __tr1-full__
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
|
||||
Draft Technical Report on C++ Library Extensions]]
|
||||
[def __tr1__
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf
|
||||
TR1]]
|
||||
[def __unordered__ [link unordered Boost.Unordered]]
|
||||
[def __intrusive__ [link intrusive.unordered_set_unordered_multiset Boost.Intrusive]]
|
||||
[def __multi-index__ [@boost:/libs/multi_index/doc/index.html
|
||||
Boost Multi-Index Containers Library]]
|
||||
[def __multi-index-short__ [@boost:/libs/multi_index/doc/index.html
|
||||
Boost.MultiIndex]]
|
||||
[def __bimap__ [@boost:/libs/bimap/index.html Boost.Bimap]]
|
||||
[def __hash-function__ [@http://en.wikipedia.org/wiki/Hash_function hash function]]
|
||||
[def __hash-table__ [@http://en.wikipedia.org/wiki/Hash_table hash table]]
|
||||
|
||||
[classref boost::hash] is an implementation of the __hash-function__ object
|
||||
specified by the __tr1-full__ (TR1). It is the default hash function for
|
||||
__unordered__, __intrusive__'s unordered associative containers, and
|
||||
__multi-index-short__'s hash indicies and __bimap__'s `unordered_set_of`.
|
||||
|
||||
As it is compliant with __tr1__, it will work with:
|
||||
|
||||
* integers
|
||||
* floats
|
||||
* pointers
|
||||
* strings
|
||||
|
||||
It also implements the extension proposed by Peter Dimov in issue 6.18 of the
|
||||
__issues__ (page 63), this adds support for:
|
||||
|
||||
* arrays
|
||||
* `std::pair`
|
||||
* the standard containers.
|
||||
* extending [classref 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 [link hash.rationale rationale].
|
||||
]
|
||||
|
||||
|
||||
[endsect]
|
||||
|
@@ -1,27 +0,0 @@
|
||||
|
||||
[/ Copyright 2005-2008 Daniel James.
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[section:links Links]
|
||||
|
||||
[*A Proposal to Add Hash Tables to the Standard Library]
|
||||
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1456.html]
|
||||
The hash table proposal explains much of the design. The hash function object
|
||||
is discussed in Section D.
|
||||
|
||||
[*The C++ Standard Library Technical Report.]
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf]
|
||||
Contains the hash function specification in section 6.3.2.
|
||||
|
||||
[*Library Extension Technical Report Issues List.]
|
||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf]
|
||||
The library implements the extension described in Issue 6.18, pages 63-67.
|
||||
|
||||
[*Methods for Identifying Versioned and Plagiarised Documents]
|
||||
Timothy C. Hoad, Justin Zobel
|
||||
[@http://www.cs.rmit.edu.au/~jz/fulltext/jasist-tch.pdf]
|
||||
Contains the hash function that [funcref boost::hash_combine] is based on.
|
||||
|
||||
[endsect]
|
||||
|
@@ -1,93 +0,0 @@
|
||||
|
||||
[/ Copyright 2005-2008 Daniel James.
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[section:portability Portability]
|
||||
|
||||
[def __boost_hash__ [classref boost::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.
|
||||
|
||||
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:
|
||||
|
||||
namespace foo
|
||||
{
|
||||
template <class T>
|
||||
class custom_type
|
||||
{
|
||||
T value;
|
||||
public:
|
||||
custom_type(T x) : value(x) {}
|
||||
|
||||
friend std::size_t hash_value(custom_type x)
|
||||
{
|
||||
__boost_hash__<int> hasher;
|
||||
return hasher(x.value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
On a compliant compiler, when `hash_value` is called for this type,
|
||||
it will look at the namespace inside the type and find `hash_value`
|
||||
but on a compiler which doesn't support ADL `hash_value` won't be found.
|
||||
To make things worse, some compilers which do support ADL won't find
|
||||
a friend class defined inside the class.
|
||||
|
||||
So first move the member function out of the class:
|
||||
|
||||
namespace foo
|
||||
{
|
||||
template <class T>
|
||||
class custom_type
|
||||
{
|
||||
T value;
|
||||
public:
|
||||
custom_type(T x) : value(x) {}
|
||||
|
||||
std::size_t hash(custom_type x)
|
||||
{
|
||||
__boost_hash__<T> hasher;
|
||||
return hasher(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline std::size_t hash_value(custom_type<T> x)
|
||||
{
|
||||
return x.hash();
|
||||
}
|
||||
}
|
||||
|
||||
Unfortunately, I couldn't declare hash_value as a friend, as some compilers
|
||||
don't support template friends, so instead I declared a member function to
|
||||
calculate the hash, and called it from hash_value.
|
||||
|
||||
For compilers which don't support ADL, hash_value needs to be defined in the
|
||||
boost namespace:
|
||||
|
||||
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
|
||||
namespace boost
|
||||
#else
|
||||
namespace foo
|
||||
#endif
|
||||
{
|
||||
template <class T>
|
||||
std::size_t hash_value(foo::custom_type<T> x)
|
||||
{
|
||||
return x.hash();
|
||||
}
|
||||
}
|
||||
|
||||
Full code for this example is at
|
||||
[@boost:/libs/container_hash/examples/portable.cpp /libs/container_hash/examples/portable.cpp].
|
||||
|
||||
[endsect]
|
@@ -1,50 +0,0 @@
|
||||
|
||||
[/ Copyright 2011 Daniel James.
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[section:rationale Rationale]
|
||||
|
||||
The rationale can be found in the original design
|
||||
[footnote issue 6.18 of the __issues__ (page 63)].
|
||||
|
||||
[heading Quality of the hash function]
|
||||
|
||||
Many hash functions strive to have little correlation between the input
|
||||
and output values. They attempt to uniformally distribute the output
|
||||
values for very similar inputs. This hash function makes no such
|
||||
attempt. In fact, for integers, the result of the hash function is often
|
||||
just the input value. So similar but different input values will often
|
||||
result in similar but different output values.
|
||||
This means that it is not appropriate as a general hash function. For
|
||||
example, a hash table may discard bits from the hash function resulting
|
||||
in likely collisions, or might have poor collision resolution when hash
|
||||
values are clustered together. In such cases this hash function will
|
||||
preform poorly.
|
||||
|
||||
But the standard has no such requirement for the hash function,
|
||||
it just requires that the hashes of two different values are unlikely
|
||||
to collide. Containers or algorithms
|
||||
designed to work with the standard hash function will have to be
|
||||
implemented to work well when the hash function's output is correlated
|
||||
to its input. Since they are paying that cost a higher quality hash function
|
||||
would be wasteful.
|
||||
|
||||
For other use cases, if you do need a higher quality hash function,
|
||||
then neither the standard hash function or `boost::hash` are appropriate.
|
||||
There are several options
|
||||
available. One is to use a second hash on the output of this hash
|
||||
function, such as [@http://web.archive.org/web/20121102023700/http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
Thomas Wang's hash function]. This this may not work as
|
||||
well as a hash algorithm tailored for the input.
|
||||
|
||||
For strings there are several fast, high quality hash functions
|
||||
available (for example [@http://code.google.com/p/smhasher/ MurmurHash3]
|
||||
and [@http://code.google.com/p/cityhash/ Google's CityHash]),
|
||||
although they tend to be more machine specific.
|
||||
These may also be appropriate for hashing a binary representation of
|
||||
your data - providing that all equal values have an equal
|
||||
representation, which is not always the case (e.g. for floating point
|
||||
values).
|
||||
|
||||
[endsect]
|
994
doc/ref.xml
994
doc/ref.xml
@@ -1,994 +0,0 @@
|
||||
|
||||
<!--
|
||||
Copyright Daniel James 2005-2009
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
|
||||
<library-reference>
|
||||
<section id="hash.reference.specification">
|
||||
<para>For the full specification, see section 6.3 of the
|
||||
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">C++ Standard Library Technical Report</ulink>
|
||||
and issue 6.18 of the
|
||||
<ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf">Library Extension Technical Report Issues List</ulink> (page 63).
|
||||
</para>
|
||||
</section>
|
||||
<header name="boost/container_hash/hash.hpp">
|
||||
<para>
|
||||
Defines <code><classname>boost::hash</classname></code>,
|
||||
and helper functions.
|
||||
</para>
|
||||
|
||||
<namespace name="boost">
|
||||
|
||||
<!--
|
||||
boost::hash
|
||||
-->
|
||||
|
||||
<struct name="hash">
|
||||
<template>
|
||||
<template-type-parameter name="T"/>
|
||||
</template>
|
||||
|
||||
<inherit access="public">
|
||||
<classname>std::unary_function<T, std::size_t></classname>
|
||||
</inherit>
|
||||
|
||||
<purpose><simpara>A <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">TR1</ulink> compliant hash function object.</simpara></purpose>
|
||||
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>T const&</paramtype>
|
||||
</parameter>
|
||||
<returns><para>
|
||||
<programlisting><functionname>hash_value</functionname>(val)</programlisting>
|
||||
</para></returns>
|
||||
<notes>
|
||||
<para>
|
||||
The call to <code><functionname>hash_value</functionname></code>
|
||||
is unqualified, so that custom overloads can be
|
||||
found via argument dependent lookup.
|
||||
</para>
|
||||
<para>
|
||||
This is not defined when the macro <code>BOOST_HASH_NO_EXTENSIONS</code>
|
||||
is defined. The specializations are still defined, so only the specializations
|
||||
required by TR1 are defined.
|
||||
</para>
|
||||
<para>
|
||||
Forward declared in
|
||||
<code><boost/container_hash/hash_fwd.hpp></code>
|
||||
</para>
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
</notes>
|
||||
<throws><para>
|
||||
Only throws if
|
||||
<code><functionname>hash_value</functionname>(T)</code> throws.
|
||||
</para></throws>
|
||||
</method>
|
||||
</struct>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>bool</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>bool</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>char</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>char</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>signed char</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>signed char</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>unsigned char</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>unsigned char</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>wchar_t</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>wchar_t</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>char16_t</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>char16_t</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>char32_t</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>char32_t</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>short</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>short</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>unsigned short</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>unsigned short</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>int</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>int</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>unsigned int</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>unsigned int</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>long</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>long</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>unsigned long</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>unsigned long</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>long long</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>long long</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>unsigned long long</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>unsigned long long</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>float</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>float</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>double</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>double</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>long double</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>long double</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>std::string</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>std::string const&</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>std::wstring</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>std::wstring const&</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>std::u16string</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>std::u16string const&</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>std::u32string</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>std::u32string const&</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
<para><functionname>hash_value</functionname>(val) in Boost.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template>
|
||||
<template-type-parameter name="T"/>
|
||||
</template>
|
||||
<specialization>
|
||||
<template-arg>T*</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>T*</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para>Unspecified in TR1, except that equal arguments yield the same result.</para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
</struct-specialization>
|
||||
|
||||
<struct-specialization name="hash">
|
||||
<template></template>
|
||||
<specialization>
|
||||
<template-arg>std::type_index</template-arg>
|
||||
</specialization>
|
||||
<method name="operator()" cv="const">
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>std::type_index</paramtype>
|
||||
</parameter>
|
||||
<returns>
|
||||
<para><code>val.hash_code()</code></para>
|
||||
</returns>
|
||||
<throws><para>Doesn't throw</para></throws>
|
||||
</method>
|
||||
<notes>
|
||||
<para>
|
||||
Only available if it's in your standard library and Boost.Config
|
||||
is aware of it.
|
||||
</para>
|
||||
</notes>
|
||||
</struct-specialization>
|
||||
|
||||
<free-function-group name="Support functions (Boost extension).">
|
||||
|
||||
<!--
|
||||
boost::hash_combine
|
||||
-->
|
||||
|
||||
<function name="hash_combine">
|
||||
<template>
|
||||
<template-type-parameter name="T"/>
|
||||
</template>
|
||||
<type>void</type>
|
||||
<parameter name="seed"><paramtype>size_t &</paramtype></parameter>
|
||||
<parameter name="v"><paramtype>T const&</paramtype></parameter>
|
||||
<purpose><simpara>
|
||||
Called repeatedly to incrementally create a hash value from
|
||||
several variables.
|
||||
</simpara></purpose>
|
||||
<effects>
|
||||
Updates <code>seed</code> with a new hash value generated by
|
||||
combining it with the result of
|
||||
<code><functionname>hash_value</functionname>(v)</code>. Will
|
||||
always produce the same result for the same combination of
|
||||
<code>seed</code> and
|
||||
<code><functionname>hash_value</functionname>(v)</code> during
|
||||
the single run of a program.
|
||||
</effects>
|
||||
<notes>
|
||||
<para><functionname>hash_value</functionname> is called without
|
||||
qualification, so that overloads can be found via ADL.</para>
|
||||
<para>This is an extension to TR1</para>
|
||||
<para>
|
||||
Forward declared in
|
||||
<code><boost/container_hash/hash_fwd.hpp></code>
|
||||
</para>
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
</notes>
|
||||
<throws>
|
||||
Only throws if <functionname>hash_value</functionname>(T) throws.
|
||||
Strong exception safety, as long as <functionname>hash_value</functionname>(T)
|
||||
also has strong exception safety.
|
||||
</throws>
|
||||
</function>
|
||||
|
||||
<!--
|
||||
boost::hash_range
|
||||
-->
|
||||
|
||||
<overloaded-function name="hash_range">
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="It"/>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="first"><paramtype>It</paramtype></parameter>
|
||||
<parameter name="last"><paramtype>It</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="It"/>
|
||||
</template>
|
||||
<type>void</type>
|
||||
<parameter name="seed"><paramtype>std::size_t&</paramtype></parameter>
|
||||
<parameter name="first"><paramtype>It</paramtype></parameter>
|
||||
<parameter name="last"><paramtype>It</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<purpose><simpara>
|
||||
Calculate the combined hash value of the elements of an iterator
|
||||
range.
|
||||
</simpara></purpose>
|
||||
<effects>
|
||||
<para>For the two argument overload:
|
||||
<programlisting>
|
||||
size_t seed = 0;
|
||||
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
<functionname>hash_combine</functionname>(seed, *first);
|
||||
}
|
||||
|
||||
return seed;
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>For the three arguments overload:</para>
|
||||
<programlisting>
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
<functionname>hash_combine</functionname>(seed, *first);
|
||||
}
|
||||
</programlisting>
|
||||
</effects>
|
||||
<notes>
|
||||
<para>
|
||||
<code>hash_range</code> is sensitive to the order of the elements
|
||||
so it wouldn't be appropriate to use this with an unordered
|
||||
container.
|
||||
</para>
|
||||
<para>This is an extension to TR1</para>
|
||||
<para>
|
||||
Forward declared in
|
||||
<code><boost/container_hash/hash_fwd.hpp></code>
|
||||
</para>
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
</notes>
|
||||
<throws><para>
|
||||
Only throws if <code><functionname>hash_value</functionname>(std::iterator_traits<It>::value_type)</code>
|
||||
throws. <code>hash_range(std::size_t&, It, It)</code> has basic exception safety as long as
|
||||
<code><functionname>hash_value</functionname>(std::iterator_traits<It>::value_type)</code>
|
||||
has basic exception safety.
|
||||
</para></throws>
|
||||
</overloaded-function>
|
||||
|
||||
</free-function-group>
|
||||
|
||||
<free-function-group name="Overloadable hash implementation (Boost extension).">
|
||||
|
||||
<!--
|
||||
boost::hash_value - integers
|
||||
-->
|
||||
|
||||
<overloaded-function name="hash_value">
|
||||
<purpose><simpara>
|
||||
Implementation of the hash function.
|
||||
</simpara></purpose>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>bool</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>char</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>signed char</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>unsigned char</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>wchar_t</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>char16_t</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>char32_t</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>short</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>unsigned short</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>int</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>unsigned int</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>long</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>unsigned long</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>long long</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>unsigned long long</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>float</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>double</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>long double</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template><template-type-parameter name="T"/></template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>T* const&</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="T"/>
|
||||
<template-nontype-parameter name="N"><type>unsigned</type></template-nontype-parameter>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter><paramtype>T (&val)[N]</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="T"/>
|
||||
<template-nontype-parameter name="N"><type>unsigned</type></template-nontype-parameter>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter><paramtype>const T (&val)[N]</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="Ch"/>
|
||||
<template-type-parameter name="A"/>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val">
|
||||
<paramtype>std::basic_string<Ch, std::char_traits<Ch>, A> const&</paramtype>
|
||||
</parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="A"/>
|
||||
<template-type-parameter name="B"/>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::pair<A, B> const&</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="T"/>
|
||||
<template-type-parameter name="A"/>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::vector<T, A> const&</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="T"/>
|
||||
<template-type-parameter name="A"/>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::list<T, A> const&</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="T"/>
|
||||
<template-type-parameter name="A"/>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::deque<T, A> const&</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="K"/>
|
||||
<template-type-parameter name="C"/>
|
||||
<template-type-parameter name="A"/>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::set<K, C, A> const&</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="K"/>
|
||||
<template-type-parameter name="C"/>
|
||||
<template-type-parameter name="A"/>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::multiset<K, C, A> const&</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="K"/>
|
||||
<template-type-parameter name="T"/>
|
||||
<template-type-parameter name="C"/>
|
||||
<template-type-parameter name="A"/>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::map<K, T, C, A> const&</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="K"/>
|
||||
<template-type-parameter name="T"/>
|
||||
<template-type-parameter name="C"/>
|
||||
<template-type-parameter name="A"/>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::multimap<K, T, C, A> const&</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="T"/>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::complex<T> const&</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::type_index</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="T"/>
|
||||
<template-nontype-parameter name="N">
|
||||
<type>std::size_t</type>
|
||||
</template-nontype-parameter>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::array<T, N> const&</paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<signature>
|
||||
<template>
|
||||
<template-type-parameter name="T" pack="1"/>
|
||||
</template>
|
||||
<type>std::size_t</type>
|
||||
<parameter name="val"><paramtype>std::tuple<T...></paramtype></parameter>
|
||||
</signature>
|
||||
|
||||
<description><para>
|
||||
Generally shouldn't be called directly by users, instead they should use
|
||||
<classname>boost::hash</classname>, <functionname>boost::hash_range</functionname>
|
||||
or <functionname>boost::hash_combine</functionname> which
|
||||
call <code>hash_value</code> without namespace qualification so that overloads
|
||||
for custom types are found via ADL.
|
||||
</para></description>
|
||||
|
||||
<notes>
|
||||
<para>This is an extension to TR1</para>
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
</notes>
|
||||
|
||||
<throws>
|
||||
Only throws if a user supplied version of
|
||||
<code><functionname>hash_value</functionname></code>
|
||||
throws for an element of a container, or
|
||||
one of the types stored in a pair.
|
||||
</throws>
|
||||
|
||||
<returns>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Types</entry>
|
||||
<entry>Returns</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><code>bool</code>,
|
||||
<code>char</code>, <code>signed char</code>, <code>unsigned char</code>,
|
||||
<code>wchar_t</code>, <code>char16_t</code>, <code>char32_t</code>,
|
||||
<code>short</code>, <code>unsigned short</code>,
|
||||
<code>int</code>, <code>unsigned int</code>, <code>long</code>, <code>unsigned long</code>
|
||||
</entry>
|
||||
<entry><code>val</code></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>long long</code>, <code>unsigned long long</code></entry>
|
||||
<entry><code>val</code> when <code>abs(val) <= std::numeric_limits<std::size_t>::max()</code>.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>float</code>, <code>double</code>, <code>long double</code></entry>
|
||||
<entry>An unspecified value, except that equal arguments shall yield the same result.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>T*</code></entry>
|
||||
<entry>An unspecified value, except that equal arguments shall yield the same result.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<code>T val[N]</code>,
|
||||
<code>const T val[N]</code>
|
||||
</entry>
|
||||
<entry><code>hash_range(val, val+N)</code></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<code>std:basic_string<Ch, std::char_traits<Ch>, A></code>,
|
||||
<code>std::vector<T, A></code>,
|
||||
<code>std::list<T, A></code>,
|
||||
<code>std::deque<T, A></code>,
|
||||
<code>std::set<K, C, A></code>,
|
||||
<code>std::multiset<K, C, A></code>,
|
||||
<code>std::map<K, T, C, A></code>,
|
||||
<code>std::multimap<K, T, C, A></code>,
|
||||
<code>std::array<T, N></code>
|
||||
</entry>
|
||||
<entry><code>hash_range(val.begin(), val.end())</code></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>std::pair<A, B></code></entry>
|
||||
<entry><programlisting>size_t seed = 0;
|
||||
<functionname>hash_combine</functionname>(seed, val.first);
|
||||
<functionname>hash_combine</functionname>(seed, val.second);
|
||||
return seed;</programlisting></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>std::tuple<T...></code></entry>
|
||||
<entry><programlisting>size_t seed = 0;
|
||||
<functionname>hash_combine</functionname>(seed, get<0>(val));
|
||||
<functionname>hash_combine</functionname>(seed, get<1>(val));
|
||||
// ....
|
||||
return seed;</programlisting></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<code>std::complex<T></code>
|
||||
</entry>
|
||||
<entry>When <code>T</code> is a built in type and <code>val.imag() == 0</code>, the result is equal to <code>hash_value(val.real())</code>. Otherwise an unspecified value, except that equal arguments shall yield the same result.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<code>std::type_index</code>
|
||||
</entry>
|
||||
<entry><code>val.hash_code()</code></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</returns>
|
||||
</overloaded-function>
|
||||
</free-function-group>
|
||||
</namespace>
|
||||
</header>
|
||||
</library-reference>
|
||||
|
@@ -1,27 +0,0 @@
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
|
||||
//[ get_hashes
|
||||
template <class Container>
|
||||
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),
|
||||
boost::hash<typename Container::value_type>());
|
||||
|
||||
return hashes;
|
||||
}
|
||||
//]
|
||||
|
||||
int main() {
|
||||
std::vector<int> values;
|
||||
values.push_back(10);
|
||||
values.push_back(20);
|
||||
|
||||
std::vector<std::size_t> hashes = get_hashes(values);
|
||||
assert(hashes[0] = boost::hash<int>()(values[0]));
|
||||
assert(hashes[1] = boost::hash<int>()(values[1]));
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
|
||||
[/ Copyright 2005-2008 Daniel James.
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[section:acknowledgements Acknowledgements]
|
||||
|
||||
This library is based on the design by Peter Dimov. During the initial
|
||||
development
|
||||
Joaquín M López Muñoz made many useful suggestions and contributed fixes.
|
||||
|
||||
The formal review was managed by Thorsten Ottosen, and the library reviewed by:
|
||||
David Abrahams, Alberto Barbati, Topher Cooper, Caleb Epstein, Dave Harris,
|
||||
Chris Jefferson, Bronek Kozicki, John Maddock, Tobias Swinger, Jaap Suter,
|
||||
Rob Stewart and Pavel Vozenilek. Since then, further constructive criticism has
|
||||
been made by Daniel Krügler, Alexander Nasonov and 沈慧峰.
|
||||
|
||||
The implementation of the hash function for pointers is based on suggestions
|
||||
made by Alberto Barbati and Dave Harris. Dave Harris also suggested an
|
||||
important improvement to [funcref boost::hash_combine] that was taken up.
|
||||
|
||||
Some useful improvements to the floating point hash algorithm were suggested
|
||||
by Daniel Krügler.
|
||||
|
||||
The original implementation came from Jeremy B. Maitin-Shepard's hash table
|
||||
library, although this is a complete rewrite.
|
||||
|
||||
[endsect]
|
207
doc/tutorial.qbk
207
doc/tutorial.qbk
@@ -1,207 +0,0 @@
|
||||
|
||||
[/ Copyright 2005-2008 Daniel James.
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[quickbook 1.7]
|
||||
[import samples/tutorial.cpp]
|
||||
|
||||
[def __multi-index-short__ [@boost:/libs/multi_index/doc/index.html
|
||||
Boost.MultiIndex]]
|
||||
|
||||
[section:tutorial Tutorial]
|
||||
|
||||
When using a hash index with __multi-index-short__, you don't need to do
|
||||
anything to use [classref boost::hash] as it uses it by default.
|
||||
To find out how to use a user-defined type, read the
|
||||
[link hash.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
|
||||
[classref boost::hash], just use an extra template parameter:
|
||||
|
||||
std::unordered_multiset<int, ``[classref boost::hash]``<int> >
|
||||
set_of_ints;
|
||||
|
||||
std::unordered_set<std::pair<int, int>, ``[classref boost::hash]``<std::pair<int, int> >
|
||||
set_of_pairs;
|
||||
|
||||
std::unordered_map<int, std::string, ``[classref boost::hash]``<int> > map_int_to_string;
|
||||
|
||||
To use [classref boost::hash] directly, create an instance and call it as a function:
|
||||
|
||||
#include <``[headerref boost/container_hash/hash.hpp]``>
|
||||
|
||||
int main()
|
||||
{
|
||||
``[classref boost::hash]``<std::string> string_hash;
|
||||
|
||||
std::size_t h = string_hash("Hash me");
|
||||
}
|
||||
|
||||
For an example of generic use, here is a function to generate a vector
|
||||
containing the hashes of the elements of a container:
|
||||
|
||||
[get_hashes]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:custom Extending boost::hash for a custom data type]
|
||||
|
||||
[classref boost::hash] is implemented by calling the function
|
||||
[funcref boost::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.
|
||||
|
||||
If you have a structure `library::book`, where each `book` is uniquely
|
||||
defined by it's member `id`:
|
||||
|
||||
namespace library
|
||||
{
|
||||
struct book
|
||||
{
|
||||
int id;
|
||||
std::string author;
|
||||
std::string title;
|
||||
|
||||
// ....
|
||||
};
|
||||
|
||||
bool operator==(book const& a, book const& b)
|
||||
{
|
||||
return a.id == b.id;
|
||||
}
|
||||
}
|
||||
|
||||
Then all you would need to do is write the function `library::hash_value`:
|
||||
|
||||
namespace library
|
||||
{
|
||||
std::size_t hash_value(book const& b)
|
||||
{
|
||||
``[classref boost::hash]``<int> hasher;
|
||||
return hasher(b.id);
|
||||
}
|
||||
}
|
||||
|
||||
And you can now use [classref boost::hash] with book:
|
||||
|
||||
library::book knife(3458, "Zane Grey", "The Hash Knife Outfit");
|
||||
library::book dandelion(1354, "Paul J. Shanley",
|
||||
"Hash & Dandelion Greens");
|
||||
|
||||
``[classref boost::hash]``<library::book> book_hasher;
|
||||
std::size_t knife_hash_value = book_hasher(knife);
|
||||
|
||||
// If std::unordered_set is available:
|
||||
std::unordered_set<library::book, ``[classref boost::hash]``<library::book> > books;
|
||||
books.insert(knife);
|
||||
books.insert(library::book(2443, "Lindgren, Torgny", "Hash"));
|
||||
books.insert(library::book(1953, "Snyder, Bernadette M.",
|
||||
"Heavenly Hash: A Tasty Mix of a Mother's Meditations"));
|
||||
|
||||
assert(books.find(knife) != books.end());
|
||||
assert(books.find(dandelion) == books.end());
|
||||
|
||||
The full example can be found in:
|
||||
[@boost:/libs/container_hash/examples/books.hpp /libs/container_hash/examples/books.hpp]
|
||||
and
|
||||
[@boost:/libs/container_hash/examples/books.cpp /libs/container_hash/examples/books.cpp].
|
||||
|
||||
[tip
|
||||
When writing a hash function, first look at how the equality function works.
|
||||
Objects that are equal must generate the same hash value.
|
||||
When objects are not equal they should generate different hash values.
|
||||
In this object equality was based just on the id so the hash function
|
||||
only hashes the id. If it was based on the object's name and author
|
||||
then the hash function should take them into account
|
||||
(how to do this is discussed in the next section).
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:combine Combining hash values]
|
||||
|
||||
Say you have a point class, representing a two dimensional location:
|
||||
|
||||
class point
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
public:
|
||||
point() : x(0), y(0) {}
|
||||
point(int x, int y) : x(x), y(y) {}
|
||||
|
||||
bool operator==(point const& other) const
|
||||
{
|
||||
return x == other.x && y == other.y;
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
[funcref boost::hash_combine] is supplied for this purpose:
|
||||
|
||||
class point
|
||||
{
|
||||
...
|
||||
|
||||
friend std::size_t hash_value(point const& p)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
``[funcref boost::hash_combine]``(seed, p.x);
|
||||
``[funcref boost::hash_combine]``(seed, p.y);
|
||||
|
||||
return 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
|
||||
[funcref boost::hash_value hash_value] on the supplied element, and combines it with the seed.
|
||||
|
||||
Full code for this example is at
|
||||
[@boost:/libs/container_hash/examples/point.cpp /libs/container_hash/examples/point.cpp].
|
||||
|
||||
[note
|
||||
When using [funcref boost::hash_combine] the order of the
|
||||
calls matters.
|
||||
'''
|
||||
<programlisting>
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine(seed, 1);
|
||||
boost::hash_combine(seed, 2);
|
||||
</programlisting>
|
||||
results in a different seed to:
|
||||
<programlisting>
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine(seed, 2);
|
||||
boost::hash_combine(seed, 1);
|
||||
</programlisting>
|
||||
'''
|
||||
If you are calculating a hash value for data where the order of the data
|
||||
doesn't matter in comparisons (e.g. a set) you will have to ensure that the
|
||||
data is always supplied in the same order.
|
||||
]
|
||||
|
||||
To calculate the hash of an iterator range you can use [funcref boost::hash_range]:
|
||||
|
||||
std::vector<std::string> some_strings;
|
||||
std::size_t hash = ``[funcref 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 [classref boost::hash],
|
||||
[funcref boost::hash_range] and [funcref boost::hash_combine]. You'll need to
|
||||
include the main header before instantiating [classref boost::hash]. When using
|
||||
a container that uses [classref 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 [@boost:/libs/container_hash/examples/template.hpp template.hpp] and
|
||||
[@boost:/libs/container_hash/examples/template.cpp template.cpp].
|
||||
|
||||
[endsect]
|
Reference in New Issue
Block a user