c++enumsunionvariant

c++ std::holds_alternative with custom type (class)?


I am learning c++23 after rust. This question explains variant matching in c++ with usage of std::visit. On the other hand, A Tour of C++ gives examples of std::holds_alternative. This example works:

struct GoodEntry {
    std::variant<float*,int> v;
};

void f(GoodEntry* pe) {
    if (std::holds_alternative<int>(pe->v)){
        std::cout << std::get<int>(pe ->v) << std::endl;
    }
}

However, this doesn't work:

struct Quit {};
struct Move { int32_t x; int32_t y; };
struct Write { std::string s; };
struct ChangeColor { int32_t r; int32_t g; int32_t b; };
using Message = std::variant<Quit, Move, Write, ChangeColor>;

void f2(Message* pm) {
    if (std::holds_alternative<Move>(pm)){
        std::cout << std::get<Move>(pm ->x) << std::endl;
    }
}

Why does compilation fail with error: no matching function for call to 'holds_alternative<Move>(Message*&)' ?


Solution

  • In your first snippet there is a struct GoodEntry that has a std::variant member field. In the second one you have a typedef Message that IS a std::variant, so you would need to first dereference your pm:

    void f2(Message* pm) {
        if (std::holds_alternative<Move>(*pm)){
            std::cout << std::get<Move>(*pm).x << std::endl;
        }
    }