Я адаптировал некоторый код из этого ответа для обработки случая, когда целевой вариант является подмножеством исходного варианта как следует:
template <class... Args>
struct variant_cast_proxy
{
std::variant<Args...> v;
template <class... ToArgs>
operator std::variant<ToArgs...>() const
{
return std::visit(
[](auto&& arg) -> std::variant<ToArgs...> {
if constexpr (std::is_convertible_v<decltype(arg), std::variant<ToArgs...>>)
return arg;
else
throw std::runtime_error("bad variant cast");
},
v
);
}
};
template <class... Args>
auto variant_cast(const std::variant<Args...>& v) -> variant_cast_proxy<Args...>
{
return { v };
}
struct A {};
struct B {};
struct C {};
struct D {};
struct E {};
struct F {};
int main() {
std::variant<A, B, C, D> v1 = B();
std::variant<B,C> v2;
v2 = variant_cast(v1);
}
Вышеприведенное работает, но я хотел бы, чтобы он обрабатывал случай, когда во время компиляции может быть обнаружено плохое преобразование. Вышеупомянутое обрабатывает все плохие преобразования во время выполнения, но возможны ошибки как во время выполнения, так и во время компиляции. Преобразование v типа std::variant<A,B,C>
в std::variant<A,B>
должно завершиться ошибкой во время выполнения, если v содержит значение типа C, но, например,
std::variant<A, B, C, D> v1 = B();
std::variant<E,F> v2;
v2 = variant_cast(v1)
даже не должен компилироваться.
Я считаю, что это можно сделать с помощью std::enable_if, но я не уверен, как именно, так как кажется, что это потребует тестирования на включение множества пакетов параметров с переменным числом параметров, что я понятия не имею, как это сделать.
error: could not convert ‘arg’ from ‘const A’ to ‘std::variant<E, F>’
- person Hillary Ryan   schedule 27.10.2020