• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Louis Dionne 2013-2017
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
4 
5 #include <boost/hana.hpp>
6 
7 #include <string>
8 #include <type_traits>
9 #include <utility>
10 namespace hana = boost::hana;
11 
12 
toStringyes13 struct yes { std::string toString() const { return "yes"; } };
14 struct no { };
15 
16 namespace has_toString_then {
17 //! [has_toString.then]
18 template <typename T, typename = void>
19 struct has_toString
20   : std::false_type
21 { };
22 
23 template <typename T>
24 struct has_toString<T, decltype((void)std::declval<T>().toString())>
25   : std::true_type
26 { };
27 //! [has_toString.then]
28 
29 static_assert(has_toString<yes>::value, "");
30 static_assert(!has_toString<no>::value, "");
31 }
32 
33 //! [has_toString.now]
34 auto has_toString = hana::is_valid([](auto&& obj) -> decltype(obj.toString()) { });
35 //! [has_toString.now]
36 
37 BOOST_HANA_CONSTANT_CHECK(has_toString(yes{}));
38 BOOST_HANA_CONSTANT_CHECK(hana::not_(has_toString(no{})));
39 
40 namespace optionalToString_then {
41 //! [optionalToString.then]
42 template <typename T>
optionalToString(T const & obj)43 auto optionalToString(T const& obj)
44   -> std::enable_if_t<decltype(has_toString(obj))::value, std::string>
45 { return obj.toString(); }
46 
47 template <typename T>
optionalToString(T const & obj)48 auto optionalToString(T const& obj)
49   -> std::enable_if_t<decltype(!has_toString(obj))::value, std::string>
50 { return "toString not defined"; }
51 //! [optionalToString.then]
52 
53 // make sure they compile
54 template std::string optionalToString(yes const&);
55 template std::string optionalToString(no const&);
56 }
57 
58 //! [optionalToString]
59 template <typename T>
optionalToString(T const & obj)60 std::string optionalToString(T const& obj) {
61   return hana::if_(has_toString(obj),
62     [](auto& x) { return x.toString(); },
63     [](auto& x) { return "toString not defined"; }
64   )(obj);
65 }
66 //! [optionalToString]
67 
68 
main()69 int main() {
70 BOOST_HANA_RUNTIME_CHECK(optionalToString(yes{}) == "yes");
71 BOOST_HANA_RUNTIME_CHECK(optionalToString(no{}) == "toString not defined");
72 
73 
74 {
75 
76 //! [non_static_member_from_object]
77 auto has_member = hana::is_valid([](auto&& x) -> decltype((void)x.member) { });
78 
79 struct Foo { int member[4]; };
80 struct Bar { };
81 BOOST_HANA_CONSTANT_CHECK(has_member(Foo{}));
82 BOOST_HANA_CONSTANT_CHECK(!has_member(Bar{}));
83 //! [non_static_member_from_object]
84 
85 }{
86 
87 //! [non_static_member_from_type]
88 auto has_member = hana::is_valid([](auto t) -> decltype(
89   (void)hana::traits::declval(t).member
90 ) { });
91 
92 struct Foo { int member[4]; };
93 struct Bar { };
94 BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
95 BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
96 //! [non_static_member_from_type]
97 
98 }{
99 
100 //! [nested_type_name]
101 auto has_member = hana::is_valid([](auto t) -> hana::type<
102   typename decltype(t)::type::member
103 //^^^^^^^^ needed because of the dependent context
104 > { });
105 
106 struct Foo { struct member; /* not defined! */ };
107 struct Bar { };
108 BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
109 BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
110 //! [nested_type_name]
111 
112 }
113 
114 }
115 
116 namespace static_member {
117 //! [static_member]
118 auto has_member = hana::is_valid([](auto t) -> decltype(
119   (void)decltype(t)::type::member
120 ) { });
121 
122 struct Foo { static int member[4]; };
123 struct Bar { };
124 BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
125 BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
126 //! [static_member]
127 }
128 
129 namespace nested_template {
130 //! [nested_template]
131 auto has_member = hana::is_valid([](auto t) -> decltype(hana::template_<
132   decltype(t)::type::template member
133   //                 ^^^^^^^^ needed because of the dependent context
134 >) { });
135 
136 struct Foo { template <typename ...> struct member; };
137 struct Bar { };
138 BOOST_HANA_CONSTANT_CHECK(has_member(hana::type_c<Foo>));
139 BOOST_HANA_CONSTANT_CHECK(!has_member(hana::type_c<Bar>));
140 //! [nested_template]
141 }
142 
143 namespace template_specialization {
144 //! [template_specialization]
145 template <typename T, typename U>
146 struct Foo;
147 
148 template <typename T>
149 struct Bar;
150 
151 auto is_binary_template = hana::is_valid([](auto trait) -> decltype(
152   trait(hana::type_c<void>, hana::type_c<void>)
153 ) { });
154 
155 BOOST_HANA_CONSTANT_CHECK(is_binary_template(hana::template_<Foo>));
156 BOOST_HANA_CONSTANT_CHECK(!is_binary_template(hana::template_<Bar>));
157 //! [template_specialization]
158 }
159