metafunction.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*!
  2. @file
  3. Forward declares `boost::hana::Metafunction`.
  4. @copyright Louis Dionne 2013-2017
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_FWD_CONCEPT_METAFUNCTION_HPP
  9. #define BOOST_HANA_FWD_CONCEPT_METAFUNCTION_HPP
  10. #include <boost/hana/config.hpp>
  11. BOOST_HANA_NAMESPACE_BEGIN
  12. //! @ingroup group-concepts
  13. //! @defgroup group-Metafunction Metafunction
  14. //! A `Metafunction` is a function that takes `hana::type`s as inputs and
  15. //! returns a `hana::type` as output.
  16. //!
  17. //! A `Metafunction` is an object satisfying the [FunctionObject][1]
  18. //! concept, but with additional requirements. First, it must be possible
  19. //! to apply a `Metafunction` to arguments whose tag is `type_tag`, and
  20. //! the result of such an application must be an object whose tag is also
  21. //! `type_tag`. Note that `hana::type` and `hana::basic_type` are the
  22. //! only such types.
  23. //!
  24. //! Secondly, a `Metafunction` must provide a nested `::%apply` template
  25. //! which allows performing the same type-level computation as is done by
  26. //! the call operator. In Boost.MPL parlance, a `Metafunction` `F` is
  27. //! hence a [MetafunctionClass][2] in addition to being a `FunctionObject`.
  28. //! Rigorously, the following must be satisfied by any object `f` of type
  29. //! `F` which is a `Metafunction`, and for arbitrary types `T...`:
  30. //! @code
  31. //! f(hana::type_c<T>...) == hana::type_c<F::apply<T...>::type>
  32. //! @endcode
  33. //!
  34. //! Thirdly, to ease the inter-operation of values and types,
  35. //! `Metafunction`s must also allow being called with arguments that
  36. //! are not `hana::type`s. In that case, the result is equivalent to
  37. //! calling the metafunction on the types of the arguments. Rigorously,
  38. //! this means that for arbitrary objects `x...`,
  39. //! @code
  40. //! f(x...) == f(hana::type_c<decltype(x)>...)
  41. //! @endcode
  42. //!
  43. //!
  44. //! Minimal complete definition
  45. //! ---------------------------
  46. //! The `Metafunction` concept does not have a minimal complete definition
  47. //! in terms of tag-dispatched methods. Instead, the syntactic requirements
  48. //! documented above should be satisfied, and the `Metafunction` struct
  49. //! should be specialized explicitly in Hana's namespace.
  50. //!
  51. //!
  52. //! Concrete models
  53. //! ---------------
  54. //! `hana::metafunction`, `hana::metafunction_class`, `hana::template_`
  55. //!
  56. //!
  57. //! Rationale: Why aren't `Metafunction`s `Comparable`?
  58. //! ---------------------------------------------------
  59. //! When seeing `hana::template_`, a question that naturally arises is
  60. //! whether `Metafunction`s should be made `Comparable`. Indeed, it
  61. //! would seem to make sense to compare two templates `F` and `G` with
  62. //! `template_<F> == template_<G>`. However, in the case where `F` and/or
  63. //! `G` are alias templates, it makes sense to talk about two types of
  64. //! comparisons. The first one is _shallow_ comparison, and it determines
  65. //! that two alias templates are equal if they are the same alias
  66. //! template. The second one is _deep_ comparison, and it determines
  67. //! that two template aliases are equal if they alias the same type for
  68. //! any template argument. For example, given `F` and `G` defined as
  69. //! @code
  70. //! template <typename T>
  71. //! using F = void;
  72. //!
  73. //! template <typename T>
  74. //! using G = void;
  75. //! @endcode
  76. //!
  77. //! shallow comparison would determine that `F` and `G` are different
  78. //! because they are two different template aliases, while deep comparison
  79. //! would determine that `F` and `G` are equal because they always
  80. //! expand to the same type, `void`. Unfortunately, deep comparison is
  81. //! impossible to implement because one would have to check `F` and `G`
  82. //! on all possible types. On the other hand, shallow comparison is not
  83. //! satisfactory because `Metafunction`s are nothing but functions on
  84. //! `type`s, and the equality of two functions is normally defined with
  85. //! deep comparison. Hence, we adopt a conservative stance and avoid
  86. //! providing comparison for `Metafunction`s.
  87. //!
  88. //! [1]: http://en.cppreference.com/w/cpp/named_req/FunctionObject
  89. //! [2]: http://www.boost.org/doc/libs/release/libs/mpl/doc/refmanual/metafunction-class.html
  90. template <typename F>
  91. struct Metafunction;
  92. BOOST_HANA_NAMESPACE_END
  93. #endif // !BOOST_HANA_FWD_CONCEPT_METAFUNCTION_HPP