Product
Concepts

## Description

Represents types that are generic containers of two elements.

This concept basically represents types that are like `std::pair`. The motivation for making such a precise concept is similar to the motivation behind the `Sequence` concept; there are many different implementations of `std::pair` in different libraries, and we would like to manipulate any of them generically.

Since a `Product` is basically a pair, it is unsurprising that the operations provided by this concept are getting the first and second element of a pair, creating a pair from two elements and other simmilar operations.

Note
  Mathematically, this concept represents types that are category theoretical products. This is also where the name comes from.

## Minimal complete definition

`first`, `second` and `make`

`first` and `second` must obviously return the first and the second element of the pair, respectively. `make` must take two arguments `x` and `y` representing the first and the second element of the pair, and return a pair `p` such that `first(p) == x` and `second(p) == y`.

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <boost/hana/first.hpp>
#include <boost/hana/pair.hpp>
#include <boost/hana/second.hpp>
namespace hana = boost::hana;
static_assert(hana::first(hana::make<hana::pair_tag>(1, 'x')) == 1, "");
static_assert(hana::second(hana::make<hana::pair_tag>(1, 'x')) == 'x', "");
int main() { }
first.hpp
Defines boost::hana::first.
boost::hana::first
constexpr auto first
Returns the first element of a pair.
Definition: first.hpp:33
boost::hana::second
constexpr auto second
Returns the second element of a pair.
Definition: second.hpp:32
boost::hana
Namespace containing everything in the library.
Definition: accessors.hpp:20
pair.hpp
Defines boost::hana::pair.
second.hpp
Defines boost::hana::second.

## Laws

For a model `P` of `Product`, the following laws must be satisfied. For every data types `X` and `Y`, there must be a unique function \( \mathtt{make} : X \times Y \to P \) such that for every `x`, `y`,

x == first(make<P>(x, y))
y == second(make<P>(x, y))

Note
  This law is less general than the universal property typically used to define category theoretical products, but it is vastly enough for what we need.

This is basically saying that a `Product` must be the most general object able to contain a pair of objects `(P1, P2)`, but nothing more. Since the categorical product is defined by a universal property, all the models of this concept are isomorphic, and the isomorphism is unique. In other words, there is one and only one way to convert one `Product` to another.

Another property that must be satisfied by `first` and `second` is that of move-independence, which ensures that we can optimally decompose a `Product` into its two members without making redundant copies.

## Refined concepts

1. `Comparable` (free model)
   Two products `x` and `y` are equal iff they are equal element-wise, by comparing the first element before the second element.
   // Copyright Louis Dionne 2013-2017
   // Distributed under the Boost Software License, Version 1.0.
   // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
   #include <boost/hana/assert.hpp>
   #include <boost/hana/equal.hpp>
   #include <boost/hana/not_equal.hpp>
   #include <boost/hana/pair.hpp>
   #include <string>
   namespace hana = boost::hana;
   using namespace std::literals;
   int main() {
   BOOST_HANA_RUNTIME_CHECK(hana::make_pair(1, "234"s) == hana::make_pair(1ll, "234"s));
   static_assert(hana::make_pair('x', 2) != hana::make_pair('y', 2), "");
   }
   assert.hpp
   Defines macros to perform different kinds of assertions.
   equal.hpp
   Defines boost::hana::equal.
   BOOST_HANA_RUNTIME_CHECK
   #define BOOST_HANA_RUNTIME_CHECK(...)
   Equivalent to BOOST_HANA_RUNTIME_ASSERT, but not influenced by the BOOST_HANA_CONFIG_DISABLE_ASSERTIO...
   Definition: assert.hpp:209
   not_equal.hpp
   Defines boost::hana::not_equal.
2. `Orderable` (free model)
   Products are ordered using a lexicographical ordering as-if they were 2-element tuples.
3. `Foldable` (free model)
   Folding a `Product` `p` is equivalent to folding a list containing `first(p)` and `second(p)`, in that order.

## Concrete models

`hana::pair`

## Variables

constexpr auto | boost::hana::first
| Returns the first element of a pair. More...
constexpr auto | boost::hana::second
| Returns the second element of a pair. More...

## Variable Documentation

## first

constexpr auto boost::hana::first

constexpr

`#include <boost/hana/fwd/first.hpp>`

Initial value:
= [](auto&& product) -> decltype(auto) {
return tag-dispatched;
}
boost::hana::product
constexpr auto product
Compute the product of the numbers of a structure.
Definition: product.hpp:57

Returns the first element of a pair.

Note that if the `Product` actually stores the elements it contains, `hana::first` is required to return a lvalue reference, a lvalue reference to const or a rvalue reference to the first element, where the type of reference must match that of the pair passed to `first`. If the `Product` does not store the elements it contains (i.e. it generates them on demand), this requirement is dropped.

## Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <boost/hana/first.hpp>
#include <boost/hana/pair.hpp>
namespace hana = boost::hana;
static_assert(hana::first(hana::make_pair(1, 'x')) == 1, "");
int main() { }

## second

constexpr auto boost::hana::second

constexpr

`#include <boost/hana/fwd/second.hpp>`

Initial value:
= [](auto&& product) -> decltype(auto) {
return tag-dispatched;
}

Returns the second element of a pair.

Note that if the `Product` actually stores the elements it contains, `hana::second` is required to return a lvalue reference, a lvalue reference to const or a rvalue reference to the second element, where the type of reference must match that of the pair passed to `second`. If the `Product` does not store the elements it contains (i.e. it generates them on demand), this requirement is dropped.

## Example

// Copyright Louis Dionne 2013-2017
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <boost/hana/second.hpp>
#include <boost/hana/pair.hpp>
namespace hana = boost::hana;
static_assert(hana::second(hana::make_pair(1, 'x')) == 'x', "");
int main() { }