Boost.Flyweight Documentation - flyweight reference

# Boost.Flyweight `flyweight` reference

Boost.Flyweight reference
Boost.Flyweight reference
Key-value flyweights

## Contents

- Header `"boost/flyweight/flyweight_fwd.hpp"` synopsis
- Header `"boost/flyweight/flyweight.hpp"` synopsis
  - Class template `flyweight`
    - Instantiation types
    - Static data initialization
    - Constructors, copy and assignment
    - Convertibility to the underlying types
    - Modifiers
    - Comparison operators
    - Specialized algorithms
    - Hash support
    - Configuration macros
- Header `"boost/flyweight/serialize.hpp"` synopsis
  - Serialization

## Header `"boost/flyweight/flyweight_fwd.hpp"` synopsis

>     #include <boost/functional/hash_fwd.hpp>
>     #include <iosfwd>

>     namespace boost{

>     namespace flyweights{

>     template<
>       typename T,
>       typename Arg1=implementation defined,
>       typename Arg2=implementation defined,
>       typename Arg3=implementation defined,
>       typename Arg4=implementation defined,
>       typename Arg5=implementation defined
>     >
>     class flyweight;

>     // comparison:

>     // OP is any of ==,<,!=,>,>=,<=

>     template<
>       typename T1,typename Arg11,...,typename Arg15,
>       typename T2,typename Arg21,...,typename Arg25
>     >
>     bool operator OP(
>       const flyweight<T1,Arg11,...,Arg15>& x,
>       const flyweight<T2,Arg21,...,Arg25>& y);

>     template<
>       typename T1,typename Arg11,...,typename Arg15,
>       typename T2
>     >
>     bool operator OP(const flyweight<T1,Arg11,...,Arg15>& x,const T2& y);

>     template<
>       typename T1,
>       typename T2,typename Arg21,...,typename Arg25
>     >
>     bool operator OP(const T1& x,const flyweight<T2,Arg21,...,Arg25>& y);

>     // specialized algorithms:

>     template<typename T,typename Arg1,...,typename Arg5>
>     inline void swap(
>       flyweight<T,Arg1,...,Arg5>& x,flyweight<T,Arg1,...,Arg5>& y);

>     template<
>       typename ElemType,typename Traits,
>       typename T,typename Arg1,...,typename Arg5
>     >
>     inline std::basic_ostream<ElemType,Traits>& operator<<(
>       std::basic_ostream<ElemType,Traits>& out,
>       const flyweight<T,Arg1,...,Arg5>& x);

>     template<
>       typename ElemType,typename Traits,
>       typename T,typename Arg1,...,typename Arg5
>     >
>     inline std::basic_ostream<ElemType,Traits>& operator>>(
>       std::basic_istream<ElemType,Traits>& in,
>       flyweight<T,Arg1,...,Arg5>& x);

>     } // namespace boost::flyweights

>     using flyweights::flyweight;

>     } // namespace boost

>     // hash support:

>     namespace std{

>     template<class T> struct hash;
>     template<typename T,typename Arg1,...,typename Arg5>
>     struct hash<boost::flyweight<T,Arg1,...,Arg5> >;

>     } // namespace std

>     namespace boost{
>     namespace flyweights{

>     template<typename T,typename Arg1,...,typename Arg5>
>     inline std::size_t hash_value(const flyweight<T,Arg1,...,Arg5>& x);

>     } // namespace boost::flyweights
>     } // namespace boost

`flyweight_fwd.hpp` forward declares the class template `flyweight` and its associated global functions and class template specializations.

## Header `"boost/flyweight/flyweight.hpp"` synopsis

### Class template `flyweight`

Objects of type `flyweight<...>` provide access to immutable values of type `flyweight<...>::value_type`, with the following advantages over using plain `value_type` objects:

- Flyweight objects with equivalent value share the same representation (the associated `value_type` object).
- The size of flyweights is typically that of a pointer, which is in general smaller than `sizeof(value_type)`.

So, if the level of redundancy (ratio of total objects to different values) is high enough, substituting a suitable instantiation of `flyweight` for `value_type` results in a reduction in memory usage.

`flyweight` is parameterized according to some aspects:

- Types `key_value` and `value_type` (possibly equal), where `key_type` serves as a key type to lookup and construct internal shared instances of objects of `value_type`.
- An optional tag type meant to syntactically differentiate between otherwise identical instantiations.
- The factory class used to store and retrieve the shared value objects.
- The type of holder used to instantiate the flyweight factory and a mutex object, both of which are unique to each specialization of the `flyweight` class template.
- A locking policy determining the synchronization mechanisms for internal access to shared resources.
- A tracking policy which controls how values are treated when all their associated flyweight objects are destroyed.

These aspects impact the internal structure and behavior of the `flyweight` instantiation in the following manner:

- Each instantation of `flyweight` internally owns a unique factory object and a unique synchronization mutex object, both of which are created through the use of an associated holder type.
- The flyweight factory stores elements of an undisclosed type `Entry` that is implicitly convertible to `const key_type&` and also stores a subobject of `value_type`. Every flyweight object is associated to a `value_type` subobject of some `Entry` stored in the factory.
- The associated mutex object is used to protect all invocations to the insertion and deletion functions of the internal flyweight factory.
- Each flyweight object internally stores a value of some undisclosed type `Handle`. `Handle` and the `Entry` type referred to above are obtained from invocations to the associated tracking policy, in the manner described for this concept.

In what follows, we implicitly assume that `key_type` equivalence refers to the equivalence relationship induced by the factory class used. Also, two values of `value_type` are considered equivalent if they are constructed from equivalent keys, or are copies of objects constructed from equivalent keys.

>     #include <initializer_list>

>     template<
>       typename T,
>       typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5
>     >
>     class flyweight
>     {
>     public:
>       typedef dependent on T key_type;
>       typedef dependent on T value_type;

>       // static data initialization:

>       static bool init();
>       class initializer{public:initializer();};

>       // construct/copy/destroy:

>       flyweight();

>       template<typename... Args>
>       explicit flyweight(Args&&... args);

>       template<typename V>
>       flyweight(std::initializer_list<V> list);

>       flyweight(const flyweight& x);
>       flyweight(flyweight& x);
>       flyweight(const flyweight&& x);
>       flyweight(flyweight&& x);

>       explicit flyweight(const value_type& x);
>       explicit flyweight(value_type& x);
>       explicit flyweight(const value_type&& x);
>       explicit flyweight(value_type&& x);

>       template<typename V>
>       flyweight& operator=(std::initializer_list<V> list);

>       flyweight& operator=(const flyweight& x);

>       flyweight& operator=(const value_type& x);
>       flyweight& operator=(value_type&& x);

>       // convertibility to underlying type:

>       const key_type&   get_key()const;
>       const value_type& get()const;
>       operator const    value_type&()const;

>       // modifiers:

>       void swap(flyweight& x);
>     };

#### Instantiation types

`T` can be either:

- An arbitrary type,
- a type of the form `key_value<Key,Value[,KeyFromValue]>`.

In the first case, the nested types `key_type` and `value_type` are both equal to `T`. In the second case, `key_type`=`Key`, `value_type`=`Value`; we say then that the instantiation of `flyweight` is a key-value flyweight. `value_type` is the type of the values flyweight objects give access to, while value lookup is based on associated `key_type` values. `key_value` must be `Assignable` and `value_type` must be constructible from `key_type`; additionally, `key_value` must conform to any extra requirements imposed by the type of factory used. For key-value flyweights, it is guaranteed that the creation or assignment of a flyweight object results in at most one construction (or copy construction in some particular cases) of an object of `value_type`, and this construction only occurs in the case that no equivalent value existed previously in the flyweight factory.

The types `Arg1`, ... , `Arg5`, if provided, must be any of the following, in no particular order:

- A tag,
- a factory specifier,
- a holder specifier,
- a locking policy,
- a tracking policy.

No aspect can be specified twice. Each internal component of the `flyweight` instantiation is obtained through use of the corresponding specifier; for instance, the factory results from a certain (MPL) invocation of the given factory specifier, the internal mutex from the given locking policy, etc. The default configuration arguments are:

- No tagging,
- `hashed_factory<>`,
- `static_holder`,
- `simple_locking`,
- `refcounted` tracking policy.

#### Static data initialization

The static data internal to a given `flyweight` instantiation (factory instance, etc.) is constructed during the dynamic initialization phase of the program and always before the first program-wide use of the instantiated class. The following utilities can be used when more control about the moment of construction is required.

`static bool init();`

> Effects: After execution of this function the static data associated to the instantiation of `flyweight` is guaranteed to be constructed.
> Note: Concurrent execution of this function is not thread safe.

`initializer::initializer();`

> Effects: Executes `init()`.

#### Constructors, copy and assignment

`flyweight();`

> Effects: Constructs a `flyweight` object with the value `value_type(key_type())` if `flyweight` is key-value or `value_type()` otherwise.

`template<typename... Args>
explicit flyweight(Args&&... args);`

> Effects: Constructs a `flyweight` object with the value `value_type(key_type(std::forward<Args>(args)...))` if `flyweight` is key-value or `value_type(std::forward<Args>(args)...)` otherwise.
> Note: In compilers without variadic template support, the implementation replaces this constructor with a number of overloads accepting any combination of const/non-const lvalue/rvalue reference arguments up to a maximum number that can be globally configured by the user.

`template<typename V>
flyweight(std::initializer_list<V> list);`

> Effects: Constructs a `flyweight` object with the value `value_type(key_type(list))` if `flyweight` is key-value or `value_type(list)` otherwise.
> Note: The specialization for a particular `std::initializer_list<V'>` of this member function template is not available unless `key_type` is constructible from `std::initializer_list<V'>`.

`flyweight(const flyweight& x);
flyweight(flyweight& x);
flyweight(const flyweight&& x);
flyweight(flyweight&& x);`

> Effects: Constructs a `flyweight` object associated to the same value as `x`.
> Exception safety: `nothrow`.

`explicit flyweight(const value_type& x);
explicit flyweight(value_type& x);
explicit flyweight(const value_type&& x);
explicit flyweight(value_type&& x);`

> Requires: If `flyweight` is key-value, `value_type` is `Assignable` and the `Key Extractor` `KeyFromValue` must have been supplied as part of the `key_value<>` construct.
> Effects: Constructs a `flyweight` associated to a copy of `x` or with a `value_type` constructed from a key equivalent to that associated to `x`. For non-key-value flyweights, `x` is its own key; for key-value flyweights, the key is extracted through use of an object of type `KeyFromValue`.

`template<typename V>
flyweight& operator=(std::initializer_list<V> list);`

> Effects: `*this=flyweight(list)`.
> Returns: `*this`.
> Note: The specialization for a particular `std::initializer_list<V'>` of this member function template is not available unless `key_type` is constructible from `std::initializer_list<V'>`.

`flyweight& operator=(const flyweight& x);`

> Effects: Associates the `flyweight` object with the same value as `x`.
> Returns: `*this`.
> Exception safety: `nothrow`.

`flyweight& operator=(const value_type& x);
flyweight& operator=(value_type&& x);`

> Effects: `*this=flyweight(x)` (first overload), `*this=flyweight(std::move(x))` (second overload).
> Returns: `*this`.

#### Convertibility to the underlying types

`const key_type& get_key()const;`

> Returns: A copy of the key used to construct the `value_type` associated to the `flyweight` object.
> Exception safety: If `flyweight` is not key-value or if `KeyFromValue` was not provided, `nothrow`.

`const value_type& get()const;
operator const value_type&()const;`

> Returns: The value associated to the `flyweight` object.
> Exception safety: `nothrow`.

#### Modifiers

`void swap(flyweight& x);`

> Effects: Swaps the associations to `value_type`s each flyweight object has. No swapping of `key_type` or `value_type` objects is done.
> Exception safety: `nothrow`.

#### Comparison operators

`template<
typename T1,typename Arg11,...,typename Arg15,
typename T2,typename Arg21,...,typename Arg25
>
bool operator ==(
const flyweight<T1,Arg11,...,Arg15>& x,
const flyweight<T2,Arg21,...,Arg25>& y);`

> Returns: If `x` and `y` are of the same type, returns `true` if and only if they are associated to the same value; if `x` and `y` have different types, returns `x.get()==y.get()`.
> Exception safety: If `x` and `y` are of the same type, `nothrow`.

`template<
typename T1,typename Arg11,...,typename Arg15,
typename T2
>
bool operator ==(const flyweight<T1,Arg11,...,Arg15>& x,const T2& y);`

> Returns: `x.get()==y`.

`template<
typename T1,
typename T2,typename Arg21,...,typename Arg25
>
bool operator ==(const T1& x,const flyweight<T2,Arg21,...,Arg25>& y);`

> Returns: `x==y.get()`.

`template<
typename T1,typename Arg11,...,typename Arg15,
typename T2,typename Arg21,...,typename Arg25
>
bool operator <(
const flyweight<T1,Arg11,...,Arg15>& x,
const flyweight<T2,Arg21,...,Arg25>& y);`

> Returns: `x.get()<y.get()`.

`template<
typename T1,typename Arg11,...,typename Arg15,
typename T2
>
bool operator <(const flyweight<T1,Arg11,...,Arg15>& x,const T2& y);`

> Returns: `x.get()<y`.

`template<
typename T1,
typename T2,typename Arg21,...,typename Arg25
>
bool operator <(const T1& x,const flyweight<T2,Arg21,...,Arg25>& y);`

> Returns: `x<y.get()`.

`template<
typename T1,typename Arg11,...,typename Arg15,
typename T2,typename Arg21,...,typename Arg25
>
bool operator OP(
const flyweight<T1,Arg11,...,Arg15>& x,
const flyweight<T2,Arg21,...,Arg25>& y);
template<
typename T1,typename Arg11,...,typename Arg15,
typename T2
>
bool operator OP(const flyweight<T1,Arg11,...,Arg15>& x,const T2& y); template<
typename T1,
typename T2,typename Arg21,...,typename Arg25
>
bool operator OP(const T1& x,const flyweight<T2,Arg21,...,Arg25>& y);`

(`OP` is any of `!=`, `>`, `>=`, `<=`.)

> Returns: `true` if and only if

> > `!(x==y)` (`OP` is `!=`),
> > `y< x` (`OP` is `>` ),
> > `!(x< y)` (`OP` is `>=`),
> > `!(y< x)` (`OP` is `<=`).

#### Specialized algorithms

`template<typename T,typename Arg1,...,typename Arg5>
inline void swap(
flyweight<T,Arg1,...,Arg5>& x,flyweight<T,Arg1,...,Arg5>& y);`

> Effects: `x.swap(y)`.

`template<
typename ElemType,typename Traits,
typename T,typename Arg1,...,typename Arg5
>
inline std::basic_ostream<ElemType,Traits>& operator<<(
std::basic_ostream<ElemType,Traits>& out,
const flyweight<T,Arg1,...,Arg5>& x);`

> Effects: `out<<x.get()`.
> Returns: `out`.

`template<
typename ElemType,typename Traits,
typename T,typename Arg1,...,typename Arg5
>
inline std::basic_ostream<ElemType,Traits>& operator>>(
std::basic_istream<ElemType,Traits>& in,
flyweight<T,Arg1,...,Arg5>& x);`

> Requires: If `flyweight` is key-value, `value_type` is `Assignable` and the `Key Extractor` `KeyFromValue` must have been supplied as part of the `key_value<>` construct.
> Effects: Reads an object of type `value_type` from `in` and assigns it to `x`.
> Returns: `in`.

#### Hash support

Support is provided for hashing `flyweight`s both with `std::hash` and `boost::hash`. In either case, the calculation does not involve hashing the associated `value_type` objects themselves; so, it is immaterial whether `value_type` is hashable or not. The results given by `std::hash` and `boost::hash` for the same `flyweight` object will usually differ.
Note: Hash support can be disabled to solve clashes with code where this has already been defined by the user.

`namespace std{
template<typename T,typename Arg1,...,typename Arg5>
struct hash<boost::flyweight<T,Arg1,...,Arg5> >;
}`

> This template specialization meets the requirements of class template `std::hash` in [unord.hash]. No exception is thrown when invoking instances of this specialization.

`template<typename T,typename Arg1,...,typename Arg5>
inline std::size_t hash_value(const flyweight<T,Arg1,...,Arg5>& x);`

> Returns: A hash value for `x` to be used by Boost.Hash.
> Exception safety: `nothrow`.

#### Configuration macros

`BOOST_FLYWEIGHT_LIMIT_PERFECT_FWD_ARGS`

> In compilers without variadic template support, globally define this macro to set the maximum number of arguments accepted by `flyweight` forwarding constructor, which by default is 5.

`BOOST_FLYWEIGHT_DISABLE_HASH_SUPPORT`

> If defined, hash support is not provided. This can be useful to cope with legacy code where general `flyweight` hashing has already been defined by the user.

## Header `"boost/flyweight/serialize.hpp"` synopsis

`serialize.hpp` includes the necessary functionality for interoperability of `flyweight` with Boost.Serialization.

### Serialization

`flyweight`s can be archived and retrieved by means of Boost.Serialization. Regular as well as XML archives are supported. Serialization is done in an efficient manner so that saving equivalent `flyweight`s result in their common `key_type` value being stored only once, regardless of whether `key_type` is tracked by Boost.Serialization or not.

Operation: saving of a `flyweight` object `x` to an output archive (XML archive) `ar`.

> Requires: `key_type` is serializable (XML-serializable).
> Effects: The value `k=x.get_key()` is saved into `ar` as part of this operation or of a previous saving operation of a `flyweight` object with the same key.
> Exception safety: Strong with respect to `x`. If an exception is thrown, `ar` may be left in an inconsistent state.

Operation: loading of a `flyweight` `x'` from an input archive (XML archive) `ar`.

> Requires: `key_type` is serializable (XML-serializable).
> Effects: `x'` is associated to a value constructed from a key equivalent to `k'`, a restored copy of the value `k` defined above.
> Exception safety: Strong with respect to `x'`. If an exception is thrown, `ar` may be left in an inconsistent state.

Boost.Flyweight reference
Boost.Flyweight reference
Key-value flyweights

Revised April 24th 2019

© Copyright 2006-2019 Joaquín M López Muñoz. 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)