3

I have the following code:

std::variant<A, B> foo();
std::variant<A, B, C> bar();
std::variant<A, B, C> foobar(bool a) {
    if (a) {
        return foo();
    } else {
        return bar();
    }
}

However, this doesn't compile on gcc:

error: could not convert ‘foo()’ from ‘variant<A, B>’ to ‘variant<A,B,C>’.

Is there an elegant way to convert std::variant<A, B> into std::variant<A, B, C>?

Ward Segers
  • 519
  • 5
  • 17

2 Answers2

1

Is there an elegant way to convert std::variant<A, B> into std::variant<A, B, C>?

No, I suppose.

The best I can imagine pass through std::visit(); something as

std::variant<A, B, C> foobar (bool a)
 {
   if (a) 
      return std::visit([](auto && val) -> std::variant<A, B, C>
                        { return {std::forward<decltype(val)>(val)}; },
                        foo());
   else
      return bar();
 }

A more general solution, could be a convVariant() function

template <typename R, typename T>
R convVariant (T && t)
 {
   return std::visit([](auto && val) -> R
                        { return {std::forward<decltype(val)>(val)}; },
                        std::forward<T>(t));
 }

so foobar() become

std::variant<A, B, C> foobar (bool a)
 {
   if (a) 
      return convVariant<std::variant<A, B, C>>(foo());
   else
      return bar();
 }
max66
  • 65,235
  • 10
  • 71
  • 111
1

In principle, the standard could allow implicit (if guaranteed successful) or explicit (otherwise) conversion from std::variant<T...> to std::variant<U...> if all types in the former occurred at least as often in the latter, as there is an unambiguous and obvious mapping.

Unfortunately, it simply doesn't.

Thus, you have to write your own function for converting.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118