1 | #pragma once |
2 | |
3 | #include <type_traits> |
4 | |
5 | #include <nlohmann/detail/meta/void_t.hpp> |
6 | |
7 | // http://en.cppreference.com/w/cpp/experimental/is_detected |
8 | namespace nlohmann |
9 | { |
10 | namespace detail |
11 | { |
12 | struct nonesuch |
13 | { |
14 | nonesuch() = delete; |
15 | ~nonesuch() = delete; |
16 | nonesuch(nonesuch const&) = delete; |
17 | nonesuch(nonesuch const&&) = delete; |
18 | void operator=(nonesuch const&) = delete; |
19 | void operator=(nonesuch&&) = delete; |
20 | }; |
21 | |
22 | template <class Default, |
23 | class AlwaysVoid, |
24 | template <class...> class Op, |
25 | class... Args> |
26 | struct detector |
27 | { |
28 | using value_t = std::false_type; |
29 | using type = Default; |
30 | }; |
31 | |
32 | template <class Default, template <class...> class Op, class... Args> |
33 | struct detector<Default, void_t<Op<Args...>>, Op, Args...> |
34 | { |
35 | using value_t = std::true_type; |
36 | using type = Op<Args...>; |
37 | }; |
38 | |
39 | template <template <class...> class Op, class... Args> |
40 | using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t; |
41 | |
42 | template <template <class...> class Op, class... Args> |
43 | using detected_t = typename detector<nonesuch, void, Op, Args...>::type; |
44 | |
45 | template <class Default, template <class...> class Op, class... Args> |
46 | using detected_or = detector<Default, void, Op, Args...>; |
47 | |
48 | template <class Default, template <class...> class Op, class... Args> |
49 | using detected_or_t = typename detected_or<Default, Op, Args...>::type; |
50 | |
51 | template <class Expected, template <class...> class Op, class... Args> |
52 | using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>; |
53 | |
54 | template <class To, template <class...> class Op, class... Args> |
55 | using is_detected_convertible = |
56 | std::is_convertible<detected_t<Op, Args...>, To>; |
57 | } // namespace detail |
58 | } // namespace nlohmann |
59 | |