admin管理员组

文章数量:1345288

I have an object of type std::variant<std::monostate, T...>, but I need to call a function that only accepts std::variant<T...>.

Is there a way I could convert a std::variant<std::monostate, T...> to std::variant<T...> if I'm sure it isn't a std::monostate?

I have an object of type std::variant<std::monostate, T...>, but I need to call a function that only accepts std::variant<T...>.

Is there a way I could convert a std::variant<std::monostate, T...> to std::variant<T...> if I'm sure it isn't a std::monostate?

Share Improve this question edited 2 days ago mkrmo 311 bronze badge asked 2 days ago gimbupgimbup 3581 gold badge4 silver badges20 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 5

You can use std::visit(), you just need to handle the case where it is std::monostate, you can throw an exception for now, or in C++23 use std::unreachable:

std::variant<std::monostate, std::string, int> monostate_variant = 2;

std::variant<std::string, int> variant2 = std::visit(
    overloads{
        [](std::monostate) ->std::variant<std::string, int> 
        { throw std::runtime_error("actually a monostate"); },
        [](auto&& obj) -> std::variant<std::string, int> 
        { return std::move(obj);}
    },
    std::move(monostate_variant)
);

The implementation of overloads is from the std::visit() cppreference page.


For the simple case that std::monostate is the first parameter, you can use this template:

template <typename...Ts>
auto remove_monostate(std::variant<std::monostate, Ts...> var)
{
    return std::visit(
    overloads{
        [](std::monostate) ->std::variant<Ts...>
        { throw std::runtime_error("actually a monostate"); },
        [](auto&& obj) -> std::variant<Ts...>
        { return std::move(obj);}
    },
    std::move(var)
    );
}

auto variant_without_monostate = remove_monostate(std::move(monostate_variant));

Online Demo

And, if their types are not in the same order, then you can modify the template and pass in the needed variant type as a template parameter, and use it as a return type for the lambdas.


C++20 perfect forwarding version (1 less move)

template <typename...Ts>
auto remove_monostate_helper(std::variant<std::monostate, Ts...>) -> std::variant<Ts...>;

template <typename T>
auto remove_monostate(T&& var)
{
    using return_type = decltype(remove_monostate_helper(var));
    return std::visit(
    overloads{
        [](std::monostate) -> return_type
        { throw std::runtime_error("actually a monostate"); },
        []<typename U>(U&& obj) -> return_type
        { return std::forward<U>(obj);}
    },
    std::forward<T>(var)
    );
}

本文标签: cConvert a stdvariantltstdmonostateTgt to stdvariantltTgtStack Overflow