Consider the following function for determining if variables of identical variant types are holding the same type:
#include <variant>
#include <iostream>
template <typename... Ts>
bool hold_same_types(const std::variant<Ts...>& v1, const std::variant<Ts...>& v2) {
return ((std::holds_alternative<Ts>(v1) && std::holds_alternative<Ts>(v2)) || ...);
}
struct foo {};
struct bar {};
struct quux {};
struct mumble {};
using var1 = std::variant<foo, bar, quux>;
int main()
{
var1 b1 = bar{};
var1 b2 = bar{};
var1 q = quux{};
std::cout << "(b1 , b2) => " << hold_same_types(b1, b2) << "\n";
std::cout << "(b1 , q) => " << hold_same_types(b1, q) << "\n";
}
There seems to be no easy way to extend hold_same_types
to handle heterogenous variants. For example, the following doesn't work
//...
using var1 = std::variant<foo, bar, quux>;
using var2 = std::variant<bar, quux, mumble>;
template <typename... Ts, typename... Us>
bool hold_same_types(const std::variant<Ts...>& v1, const std::variant<Us...>& v2) {
return ((std::holds_alternative<Ts>(v1) && std::holds_alternative<Ts>(v2)) || ...);
}
int main()
{
var1 b1 = bar{};
var2 m = mumble{};
std::cout << "(b1 , m) => " << hold_same_types(b1, m) << "\n";
}
because
You can't use multiple parameter packs like that.
Even if you could get around that, the fold expression will not compile if
Ts...
contains a type that is not inUs...
.
That is, std::holds_alternative<T>(some_variant)
will not return false if T is not an alternative in some_variant
, it won't even compile.
I've tried some more complicated approaches, but I couldn't get them to work. The main problem I run into is generally not being able to use two parameter packs.