std::variant and std::visit: error: no member named 'valueless_by_exception'

Viewed 1925

I have the following block of code:

std::visit([&](auto &&arg)
{
    using T = std::decay_t<decltype(arg)>;

    if constexpr (
        std::is_same_v<T, size_t> ||
        std::is_same_v<T, int> ||
        std::is_same_v<T, double> ||
        std::is_same_v<T, bool>
    ) {
        document->AddMember(value.first.c_str(), arg, allocator);
    }
    else if constexpr (std::is_same_v<T, std::string>){
        document->AddMember(
            rapidjson::StringRef(value.first.c_str()),
            rapidjson::StringRef(arg.c_str()),
            allocator
        );
    }
    else if constexpr (std::is_same_v<T, std::shared_ptr<Serializable>>) {
        // TODO
    }
    else if constexpr (std::is_same_v<T, std::vector<std::string>>) {
        for (const auto &strVal: arg) {
            // TODO
        }
    }
    else if constexpr (std::is_same_v<T, std::vector<std::shared_ptr<Serializable>>>) {
        for (const auto &strVal: arg) {
            // TODO
        }
    }
    else {
        throw UndefinedException("Invalid type encountered in instance of serial::Serializable");
    }
}, value);

When I attempt to compile it, I get the following error:

/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/variant:1651:23: error: no member named 'valueless_by_exception' in 'std::pair<const std::__cxx11::basic_string<char>, std::variant<unsigned long, int, double, bool, std::__cxx11::basic_string<char>, std::shared_ptr<trogdor::serial::Serializable>, std::vector<std::__cxx11::basic_string<char>, std::allocator<std::__cxx11::basic_string<char> > >, std::vector<std::shared_ptr<trogdor::serial::Serializable>, std::allocator<std::shared_ptr<trogdor::serial::Serializable> > > > >'
      if ((__variants.valueless_by_exception() || ...))

I'm having trouble figuring out what that means or how to fix it. Can anyone help me understand what's going on and how I can modify my code to make it compile?

1 Answers

The arguments to std::visit (value) should be std::variants but seems to be a std::pair.

Example:

#include <string>
#include <utility>
#include <variant>

int main () {
    std::variant<std::string> foo;

    std::visit([](auto&&){}, foo);   // OK

    std::pair<std::string, std::variant<std::string>> bar;

    std::visit([](auto&&){}, bar);   // same error as you have
}

Possible solution:

std::visit([&](auto&& arg) {
    // ....
}, value.second);

Related