6

This is my code (adapted from an example on cppreference):

#include <iostream>
#include <variant>

class foo : public std::variant<int, float> {
public:
  foo(int v) : std::variant<int,float>(v) {}
  foo(float v) : std::variant<int,float>(v) {}
};

int main() {
  foo v = 5;

  std::visit([](auto &&arg) {
    using T = std::decay_t<decltype(arg)>;
    if constexpr (std::is_same_v<T, int>)
      std::cout << "int: " << arg << std::endl;
    else if constexpr (std::is_same_v<T, float>)
      std::cout << "float: " << arg << std::endl;
  }, v);
}

clang (8.0.0) eats it and correctly outputs

int: 5

However, both gcc (9.1.0) and Visual Studio 17 give an error message when compiling this. So my question is: Is this correct code according to the specification?

Replacing v in the call with static_cast<std::variant<int, float>>(v) makes all three compilers successfully compile the code, so the main question is whether std::visit should accept a value of a type derived from std::variant.

flyx
  • 35,506
  • 7
  • 89
  • 126
  • 4
    [LWG 3052](https://cplusplus.github.io/LWG/issue3052) – Barry Jun 25 '19 at 22:07
  • 2
    Is `std::variant` designed for inheritance in the first place? – Konrad Rudolph Jun 25 '19 at 23:16
  • @KonradRudolph Well wouldn't it be `final` if you weren't supposed to inherit from it? – flyx Jun 26 '19 at 08:50
  • @flyx None of the standard library classes are marked `final` but most are *not* designed for inheritance. Part of the reason is that the `final` specifier only appeared in C++11. Bottom line, don’t rely too much on the presence or absence of `final`, consult the documentation instead. If a class isn’t explicitly marked as a base class, chances are they’re not meant to be used (and work badly) as one. – Konrad Rudolph Jun 26 '19 at 10:20
  • @KonradRudolph: Fair enough. I thought that since this is a C++17 feature and `final` came with C++11 they could have used it… anyway, I'm still interested in whether this *should* work based on how `std::variant` and `std::visit` are currently defined. – flyx Jun 26 '19 at 11:29
  • Not `static_cast&>`? Also, `variant_size_v` won't work on your derived types. Consider adding a specialization. – Yakk - Adam Nevraumont Jun 26 '19 at 11:36
  • As for a specialization on variant size, see https://stackoverflow.com/a/58984580/2193968 – Jerry Jeremiah Oct 05 '21 at 07:40

0 Answers0