Date: Fri, 9 Sep 2022 13:22:59 +0200
pt., 9 wrz 2022 o 10:58 Frederick Virchanza Gotham via Std-Proposals
<std-proposals_at_[hidden]> napisaĆ(a):
>
> On Fri, Sep 9, 2022 at 12:15 AM Frederick Virchanza Gotham wrote:
> >
> > if constexpr ( std::is_same_v<U, std::monostate> )
> > {
> > return nullptr;
> > }
>
>
> One of greatest attractions in what I'm proposing is the ability to
> use the following syntax:
>
> rs232.common_base<IR232>()->Close();
>
> However . . . we of course don't want to invoke the "Close" method on
> a nullptr if the currently hosted object is a 'monostate'.
>
> Therefore I've edited the code to throw 'bad_variant_access' instead
> of returning a nullptr, as follows:
>
> template<class Base>
> static Base const volatile
> *detail_common_base(std::variant<Types...> const volatile *const arg)
> {
> std::variant<Types...> *const p = const_cast<
> std::variant<Types...> * >(arg);
>
> auto my_lambda = []<class U>(U &u) -> Base*
> {
> if constexpr ( std::is_same_v<U, std::monostate> )
> {
> throw std::bad_variant_access();
> }
> else
> {
> static_assert( std::is_base_of_v<Base,U>,
> "Base class specified to
> std::variant<Types...>::common_base() "
> "is not a base class of currently
> hosted object" );
>
> return &u;
> }
> };
>
> return std::visit<Base*>(my_lambda, *p);
> }
>
> So now we can safely do:
>
> my_variant_object.common_base<IR232>()->Close();
>
> inside a 'try' block, and we won't end up dereferencing a nullptr.
>
But sometimes I would like to avoid exceptions and simply do `noop`
when the variant is empty.
This lead me to version like:
```
std::visit(common_base([](IR232& b) { b.Close(); }, throw_exception),
my_variant_object);
std::visit(common_base([](IR232& b) { b.Close(); }, ignore_others),
my_variant_object);
std::visit(common_base([](IR232& b) { b.Close(); }, [](auto&){ /*
fallback */ }), my_variant_object);
```
This is a variant of the `overloaded` class that sometimes is used as a visitor.
This could even allow nesting in case of mixed types that do not have
common base like:
```
std::visit(common_base([](A& b) { b.Close(); }, common_base([](B& b) {
b.End(); }, throw_exception)), my_variant_with_A0_A1_B0_B1);
```
> But maybe we could simplify the syntax even further by using a new
> helper class "std::specify_base" as follows:
>
> std::variant< std::specify_base<Mammal>, Dog, Cat > my_mammal;
>
> my_mammal.common_base()->Speak();
>
> The helper class "std::specify_base" would be similar to how we have
> the likes of "std::in_place_t".
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
<std-proposals_at_[hidden]> napisaĆ(a):
>
> On Fri, Sep 9, 2022 at 12:15 AM Frederick Virchanza Gotham wrote:
> >
> > if constexpr ( std::is_same_v<U, std::monostate> )
> > {
> > return nullptr;
> > }
>
>
> One of greatest attractions in what I'm proposing is the ability to
> use the following syntax:
>
> rs232.common_base<IR232>()->Close();
>
> However . . . we of course don't want to invoke the "Close" method on
> a nullptr if the currently hosted object is a 'monostate'.
>
> Therefore I've edited the code to throw 'bad_variant_access' instead
> of returning a nullptr, as follows:
>
> template<class Base>
> static Base const volatile
> *detail_common_base(std::variant<Types...> const volatile *const arg)
> {
> std::variant<Types...> *const p = const_cast<
> std::variant<Types...> * >(arg);
>
> auto my_lambda = []<class U>(U &u) -> Base*
> {
> if constexpr ( std::is_same_v<U, std::monostate> )
> {
> throw std::bad_variant_access();
> }
> else
> {
> static_assert( std::is_base_of_v<Base,U>,
> "Base class specified to
> std::variant<Types...>::common_base() "
> "is not a base class of currently
> hosted object" );
>
> return &u;
> }
> };
>
> return std::visit<Base*>(my_lambda, *p);
> }
>
> So now we can safely do:
>
> my_variant_object.common_base<IR232>()->Close();
>
> inside a 'try' block, and we won't end up dereferencing a nullptr.
>
But sometimes I would like to avoid exceptions and simply do `noop`
when the variant is empty.
This lead me to version like:
```
std::visit(common_base([](IR232& b) { b.Close(); }, throw_exception),
my_variant_object);
std::visit(common_base([](IR232& b) { b.Close(); }, ignore_others),
my_variant_object);
std::visit(common_base([](IR232& b) { b.Close(); }, [](auto&){ /*
fallback */ }), my_variant_object);
```
This is a variant of the `overloaded` class that sometimes is used as a visitor.
This could even allow nesting in case of mixed types that do not have
common base like:
```
std::visit(common_base([](A& b) { b.Close(); }, common_base([](B& b) {
b.End(); }, throw_exception)), my_variant_with_A0_A1_B0_B1);
```
> But maybe we could simplify the syntax even further by using a new
> helper class "std::specify_base" as follows:
>
> std::variant< std::specify_base<Mammal>, Dog, Cat > my_mammal;
>
> my_mammal.common_base()->Speak();
>
> The helper class "std::specify_base" would be similar to how we have
> the likes of "std::in_place_t".
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2022-09-09 11:23:11