Consider following code:
#include <variant>
class A {};
class B {};
template<typename... Ts, typename Variant>
bool constexpr is_of(const Variant& variant)
{
return std::visit(
[](const auto& v) {
using V = std::decay_t<decltype(v)>;
return (std::is_same_v<V, Ts> || ...);
},
variant);
}
int main()
{
using Variant = std::variant<A, B>;
static_assert(is_of<A>(Variant{A{}}));
static_assert(!is_of<B>(Variant{A{}}));
static_assert(is_of<B>(Variant{B{}})); // Fails
static_assert(!is_of<A>(Variant{B{}})); // Fails
static_assert(!is_of<int>(Variant{A{}}));
static_assert(!is_of<int>(Variant{B{}}));
return 0;
}
is_of
is a function which returns whether the value in a variant matches a range of types.
Why do the two static_assert
s fail?
GCC and clang behave as expected.
I was not able to reduce the example even more.
The visit
and the fold expression seem to be crucial, when I expand it using if constexpr
, it works as expected.
typeid(V).name()
produces "class B" when outside the fold expression, but "class A" when inside. Demo. Gotta be a bug. – Rosabellestd::disjunction_v<std::is_same<V, Ts> ...>
– Hersheltemplate<class T, class...V> concept any_same = (std::same_as<T, V> || ...);
and later in lambda usereturn any_same<V, Ts...>;
– Hershel