Open frederick-vs-ja opened 1 month ago
As noticed in steve-downey/optional_ref#20, the value_or member and range interface would be problematic for these types.
value_or
I guess we can make value_or and begin etc. conditionally existing as iterator_category for many iterator types.
begin
iterator_category
```C++ namespace detail { template class optional_value_or_layer {}; template requires (!std::is_function_v && !std::is_array_v) class optional_value_or_layer { public: template constexpr T value_or(U&& u) const { static_assert(std::is_constructible_v, "Must be able to bind u to T&"); const auto& derived_self = static_cast&>(*this); return derived_self.has_value() ? *derived_self.value_ : std::forward(u); } }; template class optional_range_layer {}; template requires (!std::is_function_v && !std::is_unbounded_array_v) class optional_range_layer { public: // Since ${PAPER_NUMBER}: ${PAPER_TITLE}. // Note: P3168 and P2988 may have different flows inside LEWG/LWG. // Implementation of the range support for optional reflects P3168R2 for now. // [optional.iterators], iterator support using iterator = detail::contiguous_iterator>; // see [optional.iterators] using const_iterator = detail::contiguous_iterator>; // see [optional.iterators] // Since ${PAPER_NUMBER}: ${PAPER_TITLE}. // Note: P3168 and P2988 may have different flows inside LEWG/LWG. // Implementation of the range support for optional reflects P3168R2 for now. // [optional.iterators], iterator support constexpr iterator begin() noexcept { auto& derived_self = static_cast&>(*this); return iterator(derived_self.has_value() ? derived_self.value_ : nullptr); }; constexpr const_iterator begin() const noexcept { const auto& derived_self = static_cast&>(*this); return const_iterator(derived_self.has_value() ? derived_self.value_ : nullptr); }; constexpr iterator end() noexcept { return begin() + static_cast&>(*this).has_value(); } constexpr const_iterator end() const noexcept { return begin() + static_cast&>(*this).has_value(); } }; } // namespace detail template class optional : public detail::optional_value_or_layer, public detail::optional_range_layer { // ... }; ```
Godbolt link for rough test.
Should we make such change (in both beman::optional26::optional and P2988)?
beman::optional26::optional
As noticed in steve-downey/optional_ref#20, the
value_or
member and range interface would be problematic for these types.I guess we can make
value_or
andbegin
etc. conditionally existing asiterator_category
for many iterator types.Expand to see the implementation details
```C++ namespace detail { template
class optional_value_or_layer {};
template
requires (!std::is_function_v && !std::is_array_v)
class optional_value_or_layer {
public:
template
constexpr T value_or(U&& u) const {
static_assert(std::is_constructible_v, "Must be able to bind u to T&");
const auto& derived_self = static_cast&>(*this);
return derived_self.has_value() ? *derived_self.value_ : std::forward(u);
}
};
template
class optional_range_layer {};
template
requires (!std::is_function_v && !std::is_unbounded_array_v)
class optional_range_layer {
public:
// Since ${PAPER_NUMBER}: ${PAPER_TITLE}.
// Note: P3168 and P2988 may have different flows inside LEWG/LWG.
// Implementation of the range support for optional reflects P3168R2 for now.
// [optional.iterators], iterator support
using iterator = detail::contiguous_iterator>; // see [optional.iterators]
using const_iterator = detail::contiguous_iterator>; // see [optional.iterators]
// Since ${PAPER_NUMBER}: ${PAPER_TITLE}.
// Note: P3168 and P2988 may have different flows inside LEWG/LWG.
// Implementation of the range support for optional reflects P3168R2 for now.
// [optional.iterators], iterator support
constexpr iterator begin() noexcept {
auto& derived_self = static_cast&>(*this);
return iterator(derived_self.has_value() ? derived_self.value_ : nullptr);
};
constexpr const_iterator begin() const noexcept {
const auto& derived_self = static_cast&>(*this);
return const_iterator(derived_self.has_value() ? derived_self.value_ : nullptr);
};
constexpr iterator end() noexcept {
return begin() + static_cast&>(*this).has_value();
}
constexpr const_iterator end() const noexcept {
return begin() + static_cast&>(*this).has_value();
}
};
} // namespace detail
template
class optional : public detail::optional_value_or_layer, public detail::optional_range_layer {
// ...
};
```
Godbolt link for rough test.
Should we make such change (in both
beman::optional26::optional
and P2988)?