]>
Commit | Line | Data |
---|---|---|
b32b8144 | 1 | // Copyright Louis Dionne 2013-2017 |
7c673cae FG |
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 | ||
13 | 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> | |
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> | |
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> | |
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 | ||
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 | } |