GuillaumeDua / CppShelf

Collection of powerfuls - C++ Single-Header Libraries Files
https://guillaumedua.github.io/CppShelf/
MIT License
9 stars 1 forks source link

[ag] universal tuple-like interface lookup ? #154

Open GuillaumeDua opened 9 months ago

GuillaumeDua commented 9 months ago

Issue: Two-phase named lookup failing when universal accessor/api is defined BEFORE user-defined types.

Demo: https://godbolt.org/z/rE1P3qqc1


Note that tests are commented in the codebase for now on branche #149 , which is merged into #131 .


// --- experimentale ---

// Homogeneous interface for tuple-likes
// - csl::ag::concepts::aggregate
// - std::tuple, std::array, std::pair
// - std::ranges::subrange
// NOTE: not std::variant (variant_size, variant_alternative)
//
// TODO(Guss): tests
//

namespace csl::universal {

    // get
    //  TODO(Guss) conditionally noexcept ?
    //  WIP: requires ? Two-phase named lookup failing ? :shrug:
    template <std::size_t N>
    constexpr auto get(auto && value) noexcept -> decltype(auto) {
        using csl::ag::get;
        using std::get;
        return get<N>(csl_fwd(value));
    }
    template <typename T>
    constexpr auto get(auto && value) noexcept -> decltype(auto) {
        using csl::ag::get;
        using std::get;
        return get<T>(csl_fwd(value));
    }

    // tuple_size
    template <typename T>
    struct tuple_size;

    template <typename T>
    requires requires { std::tuple_size<T>{}; }
    struct tuple_size<T> : std::tuple_size<T>{};

    template <typename T>
    requires
        csl::ag::concepts::aggregate<T>
    and (not requires { std::tuple_size<T>{}; })
    struct tuple_size<T> : csl::ag::size<T>{};

    template <typename T>
    constexpr auto tuple_size_v = tuple_size<T>::value;

    // tuple_element
    template <std::size_t, typename>
    struct tuple_element;

    template <std::size_t index, typename T>
    requires requires { std::tuple_element<index, T>{}; }
    struct tuple_element<index, T> : std::tuple_element<index, T>{};

    template <std::size_t index, typename T>
    requires
        csl::ag::concepts::aggregate<T>
    and (not requires { std::tuple_element<index, T>{}; })
    struct tuple_element<index, T> : csl::ag::tuple_element<index, T>{};

    template <std::size_t index, typename T>
    using tuple_element_t = tuple_element<index, T>::type;

    // TODO: concept: tuplelike ?
}

Tests:

    template <typename T, char expected>
    constexpr decltype(auto) ensure_universal_get() noexcept {

        // static_assert(requires{ csl::universal::get<0>(std::declval<T>()); });
        // static_assert(requires{ csl::universal::get<char>(std::declval<T>()); });
        // static_assert(csl::universal::get<0>(T{}) == expected);
        // static_assert(csl::universal::get<char>(T{}) == expected);
    }
    // universal:
    // - tuple_size, _v
    // - tuple_element, _t

    template <typename T>
    constexpr decltype(auto) ensure_universal_tuple_size() noexcept {
        static_assert(csl::universal::tuple_size_v<T> == 1);
    }