Skip to content

Commit

Permalink
Make sure concepts inherit from an integral_constant
Browse files Browse the repository at this point in the history
Fixes #269
  • Loading branch information
ldionne committed Nov 17, 2016
1 parent b87213e commit 9fe9d2f
Show file tree
Hide file tree
Showing 46 changed files with 499 additions and 383 deletions.
31 changes: 15 additions & 16 deletions doc/tutorial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3077,14 +3077,14 @@ conjunction with `hana::when` to achieve a great deal of expressiveness.
@subsection tutorial-core-concepts Emulation of C++ concepts
The implementation of concepts in Hana is very simple. At its heart, a concept
is just a template `struct` with a nested `::%value` boolean representing
whether the given type is a _model_ of the concept:
is just a template `struct` that inherits from a boolean `integral_constant`
representing whether the given type is a _model_ of the concept:
@code{cpp}
template <typename T>
struct Concept {
static constexpr bool value = whether T models Concept;
};
struct Concept
: hana::integral_constant<bool, whether T models Concept>
{ };
@endcode
Then, one can test whether a type `T` is a model of `Concept` by looking at
Expand All @@ -3108,9 +3108,9 @@ that can be `print`ed. Our end goal is to have a template struct such as
@code{cpp}
template <typename T>
struct Printable {
static constexpr bool value = whether print_impl<tag of T> is defined;
};
struct Printable
: hana::integral_constant<bool, whether print_impl<tag of T> is defined>
{ };
@endcode
To know whether `print_impl<...>` has been defined, we'll modify `print_impl`
Expand All @@ -3124,14 +3124,13 @@ inherit from that `special_base_class` type:
@snippet example/tutorial/concepts.cpp special_base_class_customize
As you can see, `Printable<T>::%value` really only checks whether the
`print_impl<T>` struct was specialized by a custom type. In particular,
it does not even check whether the nested `::%apply` function is defined
or if it is syntactically valid. It is assumed that if one specializes
`print_impl` for a custom type, the nested `::%apply` function exists and
is correct. If it is not, a compilation error will be triggered when one
tries to call `print` on an object of that type. Concepts in Hana make the
same assumptions.
As you can see, `Printable<T>` really only checks whether the `print_impl<T>`
struct was specialized by a custom type. In particular, it does not even check
whether the nested `::%apply` function is defined or if it is syntactically
valid. It is assumed that if one specializes `print_impl` for a custom type,
the nested `::%apply` function exists and is correct. If it is not, a compilation
error will be triggered when one tries to call `print` on an object of that type.
Concepts in Hana make the same assumptions.
Since this pattern of inheriting from a special base class is quite abundant
in Hana, the library provides a dummy type called `hana::default_` that can be
Expand Down
19 changes: 11 additions & 8 deletions example/tutorial/concepts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/integral_constant.hpp>

#include <string>
#include <type_traits>
Expand All @@ -21,10 +22,11 @@ struct print_impl : special_base_class {
};

template <typename T>
struct Printable {
using Tag = hana::tag_of_t<T>;
static constexpr bool value = !std::is_base_of<special_base_class, print_impl<Tag>>::value;
};
struct Printable
: hana::integral_constant<bool,
!std::is_base_of<special_base_class, print_impl<hana::tag_of_t<T>>>::value
>
{ };
//! [special_base_class]

//! [special_base_class_customize]
Expand All @@ -49,10 +51,11 @@ struct print_impl : hana::default_ {
};

template <typename T>
struct Printable {
using Tag = hana::tag_of_t<T>;
static constexpr bool value = !hana::is_default<print_impl<Tag>>::value;
};
struct Printable
: hana::integral_constant<bool,
!hana::is_default<print_impl<hana::tag_of_t<T>>>::value
>
{ };
//! [actual]

static_assert(!Printable<void>::value, "");
Expand Down
12 changes: 7 additions & 5 deletions include/boost/hana/concept/applicative.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,18 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/lift.hpp>


BOOST_HANA_NAMESPACE_BEGIN
template <typename A>
struct Applicative {
using Tag = typename tag_of<A>::type;
static constexpr bool value = !is_default<ap_impl<Tag>>::value &&
!is_default<lift_impl<Tag>>::value;
};
struct Applicative
: hana::integral_constant<bool,
!is_default<ap_impl<typename tag_of<A>::type>>::value &&
!is_default<lift_impl<typename tag_of<A>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_CONCEPT_APPLICATIVE_HPP
14 changes: 8 additions & 6 deletions include/boost/hana/concept/comonad.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,21 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/duplicate.hpp>
#include <boost/hana/extend.hpp>
#include <boost/hana/extract.hpp>


BOOST_HANA_NAMESPACE_BEGIN
template <typename W>
struct Comonad {
using Tag = typename tag_of<W>::type;
static constexpr bool value = !is_default<extract_impl<Tag>>::value &&
(!is_default<duplicate_impl<Tag>>::value ||
!is_default<extend_impl<Tag>>::value);
};
struct Comonad
: hana::integral_constant<bool,
!is_default<extract_impl<typename tag_of<W>::type>>::value &&
(!is_default<duplicate_impl<typename tag_of<W>::type>>::value ||
!is_default<extend_impl<typename tag_of<W>::type>>::value)
>
{ };
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_CONCEPT_COMONAD_HPP
11 changes: 7 additions & 4 deletions include/boost/hana/concept/comparable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/equal.hpp>


BOOST_HANA_NAMESPACE_BEGIN
template <typename T>
struct Comparable {
using Tag = typename tag_of<T>::type;
static constexpr bool value = !is_default<equal_impl<Tag, Tag>>::value;
};
struct Comparable
: hana::integral_constant<bool,
!is_default<equal_impl<typename tag_of<T>::type,
typename tag_of<T>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_CONCEPT_COMPARABLE_HPP
10 changes: 6 additions & 4 deletions include/boost/hana/concept/constant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/value.hpp>


BOOST_HANA_NAMESPACE_BEGIN
template <typename C>
struct Constant {
using Tag = typename tag_of<C>::type;
static constexpr bool value = !is_default<value_impl<Tag>>::value;
};
struct Constant
: hana::integral_constant<bool,
!is_default<value_impl<typename tag_of<C>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_CONCEPT_CONSTANT_HPP
14 changes: 9 additions & 5 deletions include/boost/hana/concept/euclidean_ring.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,21 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/div.hpp>
#include <boost/hana/mod.hpp>


BOOST_HANA_NAMESPACE_BEGIN
template <typename R>
struct EuclideanRing {
using Tag = typename tag_of<R>::type;
static constexpr bool value = !is_default<mod_impl<Tag, Tag>>::value &&
!is_default<div_impl<Tag, Tag>>::value;
};
struct EuclideanRing
: hana::integral_constant<bool,
!is_default<mod_impl<typename tag_of<R>::type,
typename tag_of<R>::type>>::value &&
!is_default<div_impl<typename tag_of<R>::type,
typename tag_of<R>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_CONCEPT_EUCLIDEAN_RING_HPP
12 changes: 7 additions & 5 deletions include/boost/hana/concept/foldable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,19 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/fold_left.hpp>
#include <boost/hana/unpack.hpp>


BOOST_HANA_NAMESPACE_BEGIN
template <typename T>
struct Foldable {
using Tag = typename tag_of<T>::type;
static constexpr bool value = !is_default<fold_left_impl<Tag>>::value ||
!is_default<unpack_impl<Tag>>::value;
};
struct Foldable
: hana::integral_constant<bool,
!is_default<fold_left_impl<typename tag_of<T>::type>>::value ||
!is_default<unpack_impl<typename tag_of<T>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_CONCEPT_FOLDABLE_HPP
14 changes: 8 additions & 6 deletions include/boost/hana/concept/functor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,22 @@ Distributed under the Boost Software License, Version 1.0.

#include <boost/hana/fwd/concept/functor.hpp>

#include <boost/hana/config.hpp>
#include <boost/hana/adjust_if.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/transform.hpp>


BOOST_HANA_NAMESPACE_BEGIN
template <typename F>
struct Functor {
using Tag = typename tag_of<F>::type;
static constexpr bool value = !is_default<transform_impl<Tag>>::value ||
!is_default<adjust_if_impl<Tag>>::value;
};
struct Functor
: hana::integral_constant<bool,
!is_default<transform_impl<typename tag_of<F>::type>>::value ||
!is_default<adjust_if_impl<typename tag_of<F>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_CONCEPT_FUNCTOR_HPP
13 changes: 8 additions & 5 deletions include/boost/hana/concept/group.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,20 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/minus.hpp>
#include <boost/hana/negate.hpp>


BOOST_HANA_NAMESPACE_BEGIN
template <typename G>
struct Group {
using Tag = typename tag_of<G>::type;
static constexpr bool value = !is_default<negate_impl<Tag>>::value ||
!is_default<minus_impl<Tag, Tag>>::value;
};
struct Group
: hana::integral_constant<bool,
!is_default<negate_impl<typename tag_of<G>::type>>::value ||
!is_default<minus_impl<typename tag_of<G>::type,
typename tag_of<G>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_CONCEPT_GROUP_HPP
10 changes: 6 additions & 4 deletions include/boost/hana/concept/hashable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/hash.hpp>


BOOST_HANA_NAMESPACE_BEGIN
template <typename T>
struct Hashable {
using Tag = typename tag_of<T>::type;
static constexpr bool value = !is_default<hash_impl<Tag>>::value;
};
struct Hashable
: hana::integral_constant<bool,
!is_default<hash_impl<typename tag_of<T>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_CONCEPT_HASHABLE_HPP
15 changes: 9 additions & 6 deletions include/boost/hana/concept/integral_constant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,22 @@ Distributed under the Boost Software License, Version 1.0.

#include <boost/hana/config.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>


BOOST_HANA_NAMESPACE_BEGIN
namespace detail {
template <typename C, typename Tag = typename tag_of<C>::type>
struct integral_constant_dispatch {
static constexpr bool value = hana::IntegralConstant<Tag>::value;
};
struct integral_constant_dispatch
: hana::integral_constant<bool,
hana::IntegralConstant<Tag>::value
>
{ };

template <typename C>
struct integral_constant_dispatch<C, C> {
static constexpr bool value = false;
};
struct integral_constant_dispatch<C, C>
: hana::integral_constant<bool, false>
{ };
}

//! @cond
Expand Down
16 changes: 9 additions & 7 deletions include/boost/hana/concept/iterable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,24 @@ Distributed under the Boost Software License, Version 1.0.

#include <boost/hana/fwd/concept/iterable.hpp>

#include <boost/hana/config.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/default.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/integral_constant.hpp>
#include <boost/hana/drop_front.hpp>
#include <boost/hana/is_empty.hpp>


BOOST_HANA_NAMESPACE_BEGIN
template <typename It>
struct Iterable {
using Tag = typename tag_of<It>::type;
static constexpr bool value = !is_default<at_impl<Tag>>::value &&
!is_default<drop_front_impl<Tag>>::value &&
!is_default<is_empty_impl<Tag>>::value;
};
struct Iterable
: hana::integral_constant<bool,
!is_default<at_impl<typename tag_of<It>::type>>::value &&
!is_default<drop_front_impl<typename tag_of<It>::type>>::value &&
!is_default<is_empty_impl<typename tag_of<It>::type>>::value
>
{ };
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_CONCEPT_ITERABLE_HPP
Loading

0 comments on commit 9fe9d2f

Please sign in to comment.