C++ Logo


Advanced search

Re: std::variant - going from Alternative& to the enclosing variant&

From: Victor Khomenko <victor.khomenko_at_[hidden]>
Date: Tue, 15 Sep 2020 15:50:44 +0000
> Yup, but for `std::visit`, I do not think we could mix both versions, it could
> have corner cases that make hard to solve, like:
> ```
> [](auto f){}, //this will get `T&` or tag?
> []<int I>(variant_tag<V, I> t) {}, //this will be selected over `auto` or `int&`?
> ```
> Probaby if we want use same `std::visit` then we should define exactly how
> overload are chosen, something like this:
> ```
> if constexpr (callable_v<F, T&>)
> {
> return f(get<I>(v));
> }
> else if constexpr (callable_v<F, variant_tag<V, I>>) {
> return f(variant_tag<V, I>{ v });
> }
> ```

Indeed, always creating a tag may break existing code :-(

However, I hope we still can pick-and-mix.

I think the principles to resolve such corner cases are:
  (1) We must not break any existing code.
  (2) Ideally, and subject to (1) above, we should try to make the syntax as close to the current syntax as possible. That is, if one has a visitor with 100 operator()s that is used in 100 call sites of std::visit, and one has to modify one of operator()s to accept a tag, it would be nice to be able to do that without touching the other operator()s or the call sites.

Is it possible to achieve both (1) and (2)? You technique with "if constexpr" seems to attempt that, if it works. E.g. for
 [](auto f){ BODY }
If BODY uses f without accessing the tag's member functions, then auto should be bound to T&, otherwise to a tag. I hope callable_v (or some trick based on void_t) could check that, but I'm not sure.

Received on 2020-09-15 10:50:49