Example
std::array<int, 42> storage{};
const auto span = std::span(storage);
(void)span.at(0); // okay
(void)span.at(storage.size()); // throws
Puzzle
- **Can you implement
span_at
which will use[]
iffn
is noexcept andat
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); }));
};
}
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_{};
};