11

The following uses of std::visit compiles properly under gcc 7.2 but fails to compile under clang 5.0. Does anyone know what the problem is?

#include <variant>

struct S1 {int foo() { return 0; }};
struct S2 {int foo() { return 1; }};

using V = std::variant<S1, S2>;

int  bar() {
  V v;
  return std::visit([](auto& s) { return s.foo(); }, v);
}

The first error is this:

include/c++/7.2.0/variant:238:46: error: cannot cast 'std::variant<S1, S2>' to its private base class
  'std::__detail::__variant::_Variant_storage<true, S1, S2>'
  return __get(std::in_place_index<_Np>, std::forward<_Variant>(__v)._M_u);

Here is a link to godbolt shows this error: https://godbolt.org/g/5iaKUm

user2736667
  • 361
  • 1
  • 7
  • It could be possible that libstdc++'s variant uses a non-standard feature that Clang doesn't support. It compiles with `-stdlib=libc++`. – chris Oct 21 '17 at 00:58
  • Notice `std::get<0>(v)`, `std::get(v)`, etc. fail with essentially the same error (and fewer instantiation steps in between). – aschepler Oct 21 '17 at 01:05
  • Indeed, the cause of the error seems to be the same, so we can consider this a dupe. – user2736667 Oct 24 '17 at 04:39

1 Answers1

11

This is known bug 33222 that seems to only affect libstdc++'s std::variant (and other constructs using the same combination). The problem is related to friend function to templates - see the thread for more detail.

The variant from libc++ doesn't seem to use the technique of friends that libstdc++ used, so you might want to temporarily change to libc++ in the meantime.

Small update: This has been fixed in the latest trunk.

Rakete1111
  • 47,013
  • 16
  • 123
  • 162