Skip to content

Latest commit

 

History

History
74 lines (54 loc) · 1.9 KB

370.md

File metadata and controls

74 lines (54 loc) · 1.9 KB
Info

Example

std::array<int, 42> storage{};
const auto span = std::span(storage);
(void)span.at(0); // okay
(void)span.at(storage.size()); // throws

https://godbolt.org/z/ezvMvraW1

Puzzle

  • **Can you implement span_at which will use [] if fn is noexcept and at otherwise?
struct span_at; // TODO

int main() {
    using namespace boost::ut;

    std::array<int, 42> storage{};
    for (auto i = 0; i < storage.size(); ++i) { storage[i] = i; }

    "span[index]"_test = [&] {
        span_at t{storage};
        expect(0_i == t([](auto i) noexcept(true) { return i; }, 0));
        expect(2_i == t([](auto i) noexcept(true) { return i; }, 2));
        expect(41_i == t([](auto i) noexcept(true) { return i; }, 41));
        // expect(not throws([&] { (void)t([](auto i) noexcept(true) { return i; }, 42); }));
    };

    "span.at"_test = [&] {
        span_at t{storage};
        expect(0_i == t([](auto i) noexcept(false) { return i; }, 0));
        expect(2_i == t([](auto i) noexcept(false) { return i; }, 2));
        expect(41_i == t([](auto i) noexcept(false) { return i; }, 41));
        expect(throws([&] { (void)t([](auto i) noexcept(false) { return i; }, 42); }));
    };
}

https://godbolt.org/z/oTxo9aaz4

Solutions

struct span_at {
  constexpr explicit span_at(std::span<const int> span) : span_{span} { }

  [[nodiscard]] constexpr auto operator()(auto&& fn, auto index) {
    if constexpr(noexcept(fn(span_[index]))) {
      return fn(span_[index]);
    } else {
      return fn(span_.at(index));
    }
  }

 private:
  std::span<const int> span_{};
};

https://godbolt.org/z/hcnWjWodM