Boost.Hana: boost::hana::type< T > Struct Template Reference

| Boost.Hana 1.0.0 Your standard library for metaprogramming |

Synopsis of associated functions | Friends | Public Member Functions | List of all members
boost::hana::type< T > Struct Template Reference
Data types

## Description

### template<typename T>
struct boost::hana::type< T >

C++ type in value-level representation.

A `type` is a special kind of object representing a C++ type like `int`, `void`, `std::vector<float>` or anything else you can imagine.

This page explains how `type`s work at a low level. To gain intuition about type-level metaprogramming in Hana, you should read the tutorial section on type-level computations.

Note
  For subtle reasons having to do with ADL, the actual representation of `hana::type` is implementation-defined. In particular, `hana::type` may be a dependent type, so one should not attempt to do pattern matching on it. However, one can assume that `hana::type` inherits from `hana::basic_type`, which can be useful when declaring overloaded functions:
  template <typename T>
  void f(hana::basic_type<T>) {
  // do something with T
  }

## Lvalues and rvalues

When storing `type`s in heterogeneous containers, some algorithms will return references to those objects. Since we are primarily interested in accessing their nested `::type`, receiving a reference is undesirable; we would end up trying to fetch the nested `::type` inside a reference type, which is a compilation error:

auto ts = make_tuple(type_c<int>, type_c<char>);
using T = decltype(ts[0_c])::type; // error: 'ts[0_c]' is a reference!

For this reason, `type`s provide an overload of the unary `+` operator that can be used to turn a lvalue into a rvalue. So when using a result which might be a reference to a `type` object, one can use `+` to make sure a rvalue is obtained before fetching its nested `::type`:

auto ts = make_tuple(type_c<int>, type_c<char>);
using T = decltype(+ts[0_c])::type; // ok: '+ts[0_c]' is an rvalue

## Modeled concepts

1. `Comparable`
   Two types are equal if and only if they represent the same C++ type. Hence, equality is equivalent to the `std::is_same` type trait.
   // Copyright Louis Dionne 2013-2016
   // 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/type.hpp>
   namespace hana = boost::hana;
   struct T;
   struct U;
   BOOST_HANA_CONSTANT_CHECK(hana::type_c<T> == hana::type_c<T>);
   BOOST_HANA_CONSTANT_CHECK(hana::type_c<T> != hana::type_c<U>);
   int main() { }
2. `Hashable`
   The hash of a type is just that type itself. In other words, `hash` is the identity function on `hana::type`s.
   // Copyright Louis Dionne 2013-2016
   // 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/hash.hpp>
   #include <boost/hana/type.hpp>
   namespace hana = boost::hana;
   // `hana::hash` is the identity on `hana::type`s.
   BOOST_HANA_CONSTANT_CHECK(hana::equal(
   hana::hash(hana::type_c<int>),
   hana::type_c<int>
   ));
   BOOST_HANA_CONSTANT_CHECK(hana::equal(
   hana::hash(hana::type_c<void>),
   hana::type_c<void>
   ));
   int main() { }

## Synopsis of associated functions

template<typename T >
constexpr type< T > | type_c {}
| Creates an object representing the C++ type `T`. More...
constexpr auto | decltype_ = see documentation
| `decltype` keyword, lifted to Hana. More...
template<>
constexpr auto | make< type_tag > = hana::decltype_
| Equivalent to `decltype_`, provided for convenience. More...
constexpr auto | make_type = hana::make<type_tag>
| Equivalent to `make<type_tag>`, provided for convenience. More...
constexpr auto | sizeof_
| `sizeof` keyword, lifted to Hana. More...
constexpr auto | alignof_
| `alignof` keyword, lifted to Hana. More...
constexpr auto | is_valid
| Checks whether a SFINAE-friendly expression is valid. More...

## Friends

template<typename X , typename Y >
constexpr auto | operator== (X &&x, Y &&y)
| Equivalent to `hana::equal`
template<typename X , typename Y >
constexpr auto | operator!= (X &&x, Y &&y)
| Equivalent to `hana::not_equal`

## Public Member Functions

constexpr auto | operator+ () const
| Returns rvalue of self. See description.

## Associated functions

template<typename T >
template<typename T >

constexpr type<T> type_c {}

related

Creates an object representing the C++ type `T`.

template<typename T >

constexpr auto decltype_ = see documentation

related

`decltype` keyword, lifted to Hana.

`decltype_` is somewhat equivalent to `decltype` in that it returns the type of an object, except it returns it as a `hana::type` which is a first-class citizen of Hana instead of a raw C++ type. Specifically, given an object `x`, `decltype_` satisfies

decltype_(x) == type_c<decltype(x) with references stripped>

As you can see, `decltype_` will strip any reference from the object's actual type. The reason for doing so is explained below. However, any `cv`-qualifiers will be retained. Also, when given a `hana::type`, `decltype_` is just the identity function. Hence, for any C++ type `T`,

decltype_(type_c<T>) == type_c<T>

In conjunction with the way `metafunction` & al. are specified, this behavior makes it easier to interact with both types and values at the same time. However, it does make it impossible to create a `type` containing another `type` with `decltype_`. In other words, it is not possible to create a `type_c<decltype(type_c<T>)>` with this utility, because `decltype_(type_c<T>)` would be just `type_c<T>` instead of `type_c<decltype(type_c<T>)>`. This use case is assumed to be rare and a hand-coded function can be used if this is needed.

### Rationale for stripping the references

The rules for template argument deduction are such that a perfect solution that always matches `decltype` is impossible. Hence, we have to settle on a solution that's good and and consistent enough for our needs. One case where matching `decltype`'s behavior is impossible is when the argument is a plain, unparenthesized variable or function parameter. In that case, `decltype_`'s argument will be deduced as a reference to that variable, but `decltype` would have given us the actual type of that variable, without references. Also, given the current definition of `metafunction` & al., it would be mostly useless if `decltype_` could return a reference, because it is unlikely that `F` expects a reference in its simplest use case:

int i = 0;
auto result = metafunction<F>(i);

Hence, always discarding references seems to be the least painful solution.

## Example

// Copyright Louis Dionne 2013-2016
// 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/type.hpp>
namespace hana = boost::hana;
struct X { };
BOOST_HANA_CONSTANT_CHECK(hana::decltype_(X{}) == hana::type_c<X>);
BOOST_HANA_CONSTANT_CHECK(hana::decltype_(hana::type_c<X>) == hana::type_c<X>);
BOOST_HANA_CONSTANT_CHECK(hana::decltype_(1) == hana::type_c<int>);
static int const& i = 1;
BOOST_HANA_CONSTANT_CHECK(hana::decltype_(i) == hana::type_c<int const>);
int main() { }
template<typename T >
template<>

constexpr auto make< type_tag > = hana::decltype_

related

Equivalent to `decltype_`, provided for convenience.

## Example

// Copyright Louis Dionne 2013-2016
// 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/core/make.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/type.hpp>
namespace hana = boost::hana;
struct X { };
BOOST_HANA_CONSTANT_CHECK(hana::make<hana::type_tag>(X{}) == hana::type_c<X>);
BOOST_HANA_CONSTANT_CHECK(hana::make<hana::type_tag>(hana::type_c<X>) == hana::type_c<X>);
BOOST_HANA_CONSTANT_CHECK(hana::make_type(X{}) == hana::type_c<X>);
BOOST_HANA_CONSTANT_CHECK(hana::make_type(hana::type_c<X>) == hana::type_c<X>);
int main() { }
template<typename T >

constexpr auto make_type = hana::make<type_tag>

related

Equivalent to `make<type_tag>`, provided for convenience.

## Example

// Copyright Louis Dionne 2013-2016
// 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/core/make.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/type.hpp>
namespace hana = boost::hana;
struct X { };
BOOST_HANA_CONSTANT_CHECK(hana::make<hana::type_tag>(X{}) == hana::type_c<X>);
BOOST_HANA_CONSTANT_CHECK(hana::make<hana::type_tag>(hana::type_c<X>) == hana::type_c<X>);
BOOST_HANA_CONSTANT_CHECK(hana::make_type(X{}) == hana::type_c<X>);
BOOST_HANA_CONSTANT_CHECK(hana::make_type(hana::type_c<X>) == hana::type_c<X>);
int main() { }
template<typename T >

constexpr auto sizeof_

related

Initial value:
= [](auto&& x) {
using T = typename decltype(hana::decltype_(x))::type;
return hana::size_c<sizeof(T)>;
}

`sizeof` keyword, lifted to Hana.

`sizeof_` is somewhat equivalent to `sizeof` in that it returns the size of an expression or type, but it takes an arbitrary expression or a `hana::type` and returns its size as an `integral_constant`. Specifically, given an expression `expr`, `sizeof_` satisfies

sizeof_(expr) == size_t<sizeof(decltype(expr) with references stripped)>

However, given a `type`, `sizeof_` will simply fetch the size of the C++ type represented by that object. In other words,

sizeof_(type_c<T>) == size_t<sizeof(T)>

The behavior of `sizeof_` is consistent with that of `decltype_`. In particular, see `decltype_`'s documentation to understand why references are always stripped by `sizeof_`.

## Example

// Copyright Louis Dionne 2013-2016
// 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/equal.hpp>
#include <boost/hana/type.hpp>
namespace hana = boost::hana;
struct X { };
static_assert(hana::sizeof_(hana::type_c<X>) == sizeof(X), "");
static_assert(hana::sizeof_(1) == sizeof(1), "");
static_assert(hana::sizeof_(hana::type_c<int>) == sizeof(int), "");
int main() {}
template<typename T >

constexpr auto alignof_

related

Initial value:
= [](auto&& x) {
using T = typename decltype(hana::decltype_(x))::type;
return hana::size_c<alignof(T)>;
}

`alignof` keyword, lifted to Hana.

`alignof_` is somewhat equivalent to `alignof` in that it returns the alignment required by any instance of a type, but it takes a `type` and returns its alignment as an `integral_constant`. Like `sizeof` which works for expressions and type-ids, `alignof_` can also be called on an arbitrary expression. Specifically, given an expression `expr` and a C++ type `T`, `alignof_` satisfies

alignof_(expr) == size_t<alignof(decltype(expr) with references stripped)>
alignof_(type_c<T>) == size_t<alignof(T)>

The behavior of `alignof_` is consistent with that of `decltype_`. In particular, see `decltype_`'s documentation to understand why references are always stripped by `alignof_`.

## Example

// Copyright Louis Dionne 2013-2016
// 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/equal.hpp>
#include <boost/hana/type.hpp>
namespace hana = boost::hana;
struct X { };
static_assert(hana::alignof_(hana::type_c<X>) == alignof(X), "");
static_assert(hana::alignof_(1) == alignof(decltype(1)), "");
static_assert(hana::alignof_(hana::type_c<int>) == alignof(int), "");
int main() { }
template<typename T >

constexpr auto is_valid

related

Initial value:
= [](auto&& f) {
return [](auto&& ...args) {
return whether f(args...) is a valid expression;
};
}

Checks whether a SFINAE-friendly expression is valid.

Given a SFINAE-friendly function, `is_valid` returns whether the function call is valid with the given arguments. Specifically, given a function `f` and arguments `args...`,

is_valid(f, args...) == whether f(args...) is valid

The result is returned as a compile-time `Logical`. Furthermore, `is_valid` can be used in curried form as follows:

is_valid(f)(args...)

This syntax makes it easy to create functions that check the validity of a generic expression on any given argument(s).

Warning
  To check whether calling a nullary function `f` is valid, one should use the `is_valid(f)()` syntax. Indeed, `is_valid(f /* no args */)` will be interpreted as the currying of `is_valid` to `f` rather than the application of `is_valid` to `f` and no arguments.

## Example

// Copyright Louis Dionne 2013-2016
// 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/not.hpp>
#include <boost/hana/type.hpp>
#include <string>
#include <vector>
namespace hana = boost::hana;
int main() {
// Checking for a member
struct Person { std::string name; };
auto has_name = hana::is_valid([](auto&& p) -> decltype((void)p.name) { });
Person joe{"Joe"};
static_assert(has_name(joe), "");
static_assert(!has_name(1), "");
// Checking for a nested type
auto has_value_type = hana::is_valid([](auto t) -> hana::type<
typename decltype(t)::type::value_type
> { });
static_assert(has_value_type(hana::type_c<std::vector<int>>), "");
static_assert(!has_value_type(hana::type_c<Person>), "");
}