Search code examples
c++variantc++20

set a value of std::variant by index


I was trying to create something like the upcoming (if ever) std::expected using std::variant. I thought it would be very easy to something like that, yet maybe not optimal.

However, I faced some interesting exercise with std::variant and it is how to assign a value by an index? The only way how I got close to it is in the example below, which is maybe not too bad at the end, but still, looks quite weird at first glance. (yet I am not sure if it's general enough)

#include <variant>

template<typename ValueType, typename ErrorType>
class Expected
{

    std::variant<std::monostate, ValueType, ErrorType> data_;

public:
    const ValueType& GetValue()
    {
        return std::get<1>(data_);
    }

    void SetValue(auto&& value)
    {
        data_ = decltype(data_)(std::in_place_index_t<1>{}, std::forward<decltype(value)>(value));
    }

};

int main()
{
    Expected<bool, bool> e;
    e.SetValue(false);
    return e.GetValue();
}

I also got an idea that some really thin wrapper class could help here, I suppose it could be written in a way, that it would be optimized out by the compiler.

std::variant<std::monostate, ValueWrapper<ValueType>, ErrorType> data_;


Solution

  • The function you're looking for is variant::emplace. Your function becomes:

        void SetValue(auto&& value)
        {
            data_.template emplace<1>(std::forward<decltype(value)>(value));
        }