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() { }

## 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), "");
   }
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.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. More...

constexpr auto | boost::hana::second

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. More...

## Variable Documentation

constexpr auto boost::hana::first

`#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.More generally, product will take any foldable stru...
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() { }

constexpr auto boost::hana::second

`#include <boost/hana/fwd/second.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.More generally, product will take any foldable stru...
Definition: product.hpp:57

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() { }