Boost.Hana  1.1.0
Your standard library for metaprogramming
boost::hana::common< T, U, enabler > Struct Template Reference

Description

template<typename T, typename U, optional when-based enabler>
struct boost::hana::common< T, U, enabler >

Metafunction returning the common data type between two data types.

common is a natural extension of the std::common_type metafunction to data types. Given two data types T and U, we say that they share a common type C if both objects of data type T and objects of data type U may be converted (using to) to an object of data type C, and if that conversion is equality preserving. In other words, this means that for any objects t1, t2 of data type T and u1, u2 of data type U, the following law is satisfied:

to<C>(t1) == to<C>(t2) if and only if t1 == t2
to<C>(u1) == to<C>(u2) if and only if u1 == u2

The role of common is to provide an alias to such a C if it exists. In other words, if T and U have a common data type C, common<T, U>::type is an alias to C. Otherwise, common<T, U> has no nested type and can be used in dependent contexts to exploit SFINAE. By default, the exact steps followed by common to determine the common type C of T and U are

  1. If T and U are the same, then C is T.
  2. Otherwise, if true ? std::declval<T>() : std::declval<U>() is well-formed, then C is the type of this expression after using std::decay on it. This is exactly the type that would have been returned by std::common_type, except that custom specializations of std::common_type are not taken into account.
  3. Otherwise, no common data type is detected and common<T, U> does not have a nested type alias, unless it is specialized explicitly.

As point 3 suggests, it is also possible (and sometimes necessary) to specialize common in the boost::hana namespace for pairs of custom data types when the default behavior of common is not sufficient. Note that when-based specialization is supported when specializing common in the boost::hana namespace.

Rationale for requiring the conversion to be equality-preserving

This decision is aligned with a proposed concept design for the standard library (N3351). Also, if we did not require this, then all data types would trivially share the common data type void, since all objects can be converted to it.

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 <type_traits>
namespace hana = boost::hana;
struct Person { };
struct Employee : Person { };
static_assert(std::is_same<hana::common<int, float>::type, float>{}, "");
static_assert(std::is_same<hana::common<Person, Employee>::type, Person>{}, "");
int main() { }