Skip to content

Latest commit

 

History

History
231 lines (180 loc) · 6.47 KB

294.md

File metadata and controls

231 lines (180 loc) · 6.47 KB
Info

Example

#include <ranges>

template <auto Begin, auto End, auto List>
auto slice = List
           | std::ranges::views::drop(Begin)
           | std::ranges::views::take(End);

static_assert(
  slice<1_c, 2_c, boost::mp::list<int, double, float>()>
  ==
                  boost::mp::list<double, float>());

https://godbolt.org/z/hfq8Y1xEn

Puzzle

  • Can you implement algorithim which returns either last or first element of the list depending on which one has bigger size?
    list<byte[100], byte[200], byte[42]>  -> byte[100]
    list<byte[100], byte[200], byte[142]> -> byte[142]
    list<byte[100], byte[1],   byte[142]> -> byte[142]
    
template <auto List>
auto first_or_last_depending_on_size; // TODO

static_assert(first_or_last_depending_on_size<boost::mp::list<std::byte[42], std::byte[43]>()> ==
                                              boost::mp::list<std::byte[43]>());

static_assert(first_or_last_depending_on_size<boost::mp::list<std::byte[42], std::byte[999], std::byte[43]>()> ==
                                              boost::mp::list<std::byte[43]>());

static_assert(first_or_last_depending_on_size<boost::mp::list<std::byte[142], std::byte[999], std::byte[43]>()> ==
                                              boost::mp::list<std::byte[142]>());

static_assert(first_or_last_depending_on_size<boost::mp::list<std::byte[1], std::byte[2], std::byte[3], std::byte[2]>()> ==
                                              boost::mp::list<std::byte[2]>());

https://godbolt.org/z/46Thzbf8n

Solutions

template <auto List>
auto first_or_last_depending_on_size = [] consteval {
    auto LastList = List | std::ranges::views::reverse | std::ranges::views::take(1_c);
    if constexpr (auto FirstList = List | std::ranges::views::take(1_c); sizeof_list(FirstList) > sizeof_list(LastList)) {
        return FirstList;
    } else {
        return LastList;
    }
} ();

https://godbolt.org/z/PY5xdhvEc

template<template<class... Ts> class TList, class... Ts>
[[nodiscard]] consteval auto sizeof_list(TList<Ts...>) { return (sizeof(Ts) + ...);}

template<template<class... Ts> class TList, class... Ts>
[[nodiscard]] consteval auto size(TList<Ts...>) { return sizeof...(Ts); }

template <auto List>
auto first = List | std::ranges::views::take(1_c);

template <auto List>
auto last = List | std::ranges::views::drop(std::integral_constant<std::size_t, size(List) - 1>());

template <auto List>
auto first_or_last_depending_on_size = boost::mp::list<
    std::byte[std::max(sizeof_list(first<List>), sizeof_list(last<List>))]
>()

https://godbolt.org/z/K9vjM7Eao

template <auto List>
auto first_or_last_depending_on_size = List | []<class...> {
    using boost::mp::operator""_c;
    auto first = List | std::ranges::views::take(1_c);
    auto last  = List | std::ranges::views::reverse | std::ranges::views::take(1_c);
    auto size = []<class T> { return sizeof(T); };

    if constexpr ((first | size) > (last | size)) {
        return first;
    } else {
        return last;
    }
};

https://godbolt.org/z/15TY4YT89

template <auto List>
auto first_or_last_depending_on_size = List | []<class... Ts>(auto) {
    using boost::mp::operator""_c;
    auto first = List | std::ranges::views::take(1_c);
    auto last  = List | std::ranges::views::reverse | std::ranges::views::take(1_c);
    auto size =  [](auto list) { return list | []<class T> { return sizeof(T); };  };
    return std::array{
        (size(first)) > (size(last)) ?
        boost::mp::meta{.index = 0} :
        boost::mp::meta{.index = sizeof...(Ts) - 1}
    };
};

https://godbolt.org/z/hY95P6qYe

template<template<class... Ts> class TList, class... Ts>
[[nodiscard]] consteval auto sizeof_list(TList<Ts...>) { return (sizeof(Ts) + ...);}

template <auto List>
constexpr auto first = List | std::ranges::views::take(1_c);

template <auto List>
auto last = first<List | std::ranges::views::reverse>;

template <auto List>
auto first_or_last_depending_on_size =
  [] {
    if constexpr (sizeof_list(first<List>) > sizeof_list(last<List>)) {
      return first<List>;
    } else {
      return last<List>;
    }
  }();

https://godbolt.org/z/6Mec4378M

template <auto List>
auto first_or_last_depending_on_size = List | [](boost::mp::concepts::meta auto types) {
    return std::array{
        types[0].size > types[types.size() - 1].size - 1 ?
        boost::mp::meta{.index = 0} :
        boost::mp::meta{.index = types.size()-1}
    };
};

https://godbolt.org/z/4fqhTd5xj

template <auto List>
auto first_or_last_depending_on_size = []{
    constexpr auto first = List | std::views::take(1_c);
    constexpr auto last = List | std::views::reverse | std::views::take(1_c);

    if constexpr(sizeof_list(first) > sizeof_list(last)){
        return first;
    }
    else{
        return last;
    }
}();

https://godbolt.org/z/fMcEh33rY

template <auto List>
auto first_or_last_depending_on_size = [] {
    constexpr auto first = List | views::take(1_c);
    constexpr auto last =  List | views::reverse | views::take(1_c);

    if constexpr (sizeof_list(first) > sizeof_list(last)) {
        return first;
    } else {
        return last;
    }
}();

https://godbolt.org/z/cssW4cq51

template<template<class... Ts> class TList, class... Ts>
[[nodiscard]] consteval auto sizeof_list(TList<Ts...>) { return (sizeof(Ts) + ...);}

namespace rv = std::ranges::views;

template <auto List>
auto first = [] { return List | rv::take(1_c); };

template <auto List>
auto last = [] { return List | rv::reverse | rv::take(1_c); };

template <auto List>
auto first_or_last_depending_on_size = [] {
    auto first_element = first<List>();
    auto last_element = last<List>();

    if constexpr (sizeof_list(first_element) > sizeof_list(last_element)) {
        return first_element;
    } else {
        return last_element;
    }
}();

https://godbolt.org/z/x8nKj3qdn

template <auto List>
auto first_or_last_depending_on_size = List | [] (boost::mp::concepts::meta auto types) {
  auto first = types.front();
  auto last = types.back();
  return std::array{first.size < last.size ? last : first};
};

https://godbolt.org/z/jdrdhP3z8