/* try.cpp - to try out and experiment with new features.... * scons will create the binary bin/try */ // 06/25 - provide a concept to accept _tuple-like_ objects // 06/25 - investigate function type detection of std::bind Binders // 12/24 - investigate problem when perfect-forwarding into a binder // 12/24 - investigate overload resolution on a templated function similar to std::get // 11/24 - how to define a bare object location comparison predicate // 11/23 - prototype for grouping from iterator /** @file try.cpp * Develop a concept to detect _tuple-like_ classes, based on the requirements * of the »tuple protocol«. Using some ideas from [Stackoverflow] as starting point. * However, we model both a _friend function_ `get` and a similar member function * as alternatives for element access, and we break down the checks into sub-concepts. * [Stackoverflow]: https://stackoverflow.com/q/68443804/444796 */ #include "lib/format-cout.hpp" #include "lib/test/test-helper.hpp" #include "lib/test/diagnostic-output.hpp" #include "lib/meta/tuple-helper.hpp" #include "lib/hetero-data.hpp" #include "lib/util.hpp" #include using std::string; namespace lib { namespace meta { template concept tuple_sized = requires { { std::tuple_size::value } -> std::convertible_to; }; template concept tuple_adl_accessible = requires(TUP tup) { typename std::tuple_element_t; { get(tup) } -> std::convertible_to&>; }; template concept tuple_mem_accessible = requires(TUP tup) { typename std::tuple_element_t; { tup.template get() } -> std::convertible_to&>; }; template concept tuple_element_accessible = tuple_mem_accessible or tuple_adl_accessible; template concept tuple_accessible = tuple_sized and WithIdxSeq>::andAll([](auto idx) { return tuple_element_accessible; }); template concept tuple_like = not is_reference_v and tuple_sized> and tuple_accessible>; template requires(tuple_like>) decltype(auto) get (TUP&& tup) { using Tup = std::remove_reference_t; static_assert (0 < std::tuple_size_v); if constexpr (tuple_mem_accessible) { if constexpr (std::is_reference_v) return tup.template get(); else { // return value copy when tuple given as RValue using Elm = std::tuple_element_t; Elm elm(tup.template get()); return elm; } } else { using std::get; return get (std::forward (tup)); } } }}//namespace lib::meta template void show() { SHOW_TYPE(X) } template void show() { cout << "Tup!! "<< lib::test::showType() < ([](auto i) { using Elm = std::tuple_element_t; cout <<" "<() <; using Arr = std::array; using Hetero = lib::HeteroData::Chain::ChainExtent::ChainType; SHOW_EXPR((lib::meta::tuple_sized )) SHOW_EXPR((lib::meta::tuple_sized )) SHOW_EXPR((lib::meta::tuple_sized )) SHOW_EXPR((lib::meta::tuple_sized )) SHOW_EXPR((lib::meta::tuple_element_accessible)) // SHOW_EXPR((lib::meta::tuple_element_accessible)) SHOW_EXPR((lib::meta::tuple_element_accessible)) SHOW_EXPR((lib::meta::tuple_accessible)) SHOW_EXPR((lib::meta::tuple_accessible)) SHOW_EXPR((lib::meta::tuple_like )) SHOW_EXPR((lib::meta::tuple_like )) SHOW_EXPR((lib::meta::tuple_like )) SHOW_EXPR((lib::meta::tuple_like )) show(); show(); show(); show(); SHOW_EXPR((std::tuple_size_v)) using Elm1 = std::tuple_element_t<1, const Tup>; SHOW_TYPE(Elm1) using TupConstSeq = lib::meta::ElmTypes::Seq; SHOW_TYPE(TupConstSeq) using T1 = decltype(lib::meta::get<0> (std::declval())); SHOW_TYPE(T1) using T2 = decltype(lib::meta::get<0> (std::declval())); SHOW_TYPE(T2) using T3 = decltype(lib::meta::get<0> (std::declval())); SHOW_TYPE(T3) using H1 = decltype(lib::meta::get<4> (std::declval())); SHOW_TYPE(H1) using H2 = decltype(lib::meta::get<4> (std::declval())); SHOW_TYPE(H2) using H3 = decltype(lib::meta::get<4> (std::declval())); SHOW_TYPE(H3) cout << "\n.gulp." <