1 #pragma once 2 3 #include <type_traits> 4 5 #include <nlohmann/detail/meta/void_t.hpp> 6 7 // https://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