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.
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: 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:
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
:
Comparable
std::is_same
type trait. Hashable
hash
is the identity function on hana::type
s. 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. | |
Creates an object representing the C++ type T
.
|
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
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
,
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.
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:
Hence, always discarding references seems to be the least painful solution.
Equivalent to decltype_
, provided for convenience.
|
related |
Equivalent to make<type_tag>
, provided for convenience.
|
related |
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
However, given a type
, sizeof_
will simply fetch the size of the C++ type represented by that object. In other words,
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_
.
|
related |
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
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_
.
|
related |
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...
,
The result is returned as a compile-time Logical
. Furthermore, is_valid
can be used in curried form as follows:
This syntax makes it easy to create functions that check the validity of a generic expression on any given argument(s).
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.