Peter Lenkefi
Peter Lenkefi

Reputation: 1346

Pattern matching in C++

I'm writing a compiler in C++ and as any compiler, it requires an extreme amount of pattern matching and dynamic casts. In languages like Rust, Haskell, and OCaml I can destruct a type easily, like:

match node {
    Binary{ left, right, operator } => { .. }
    _ => { .. }
}

In C++ the best I can do is:

if (auto bin = dynamic_cast<Binary*>(node)) { ... }
else if (...) { ... }

Which is really limited and ugly if you introduce smart pointers into the scene. For example if I need to match 2 things for something:

bool matched = false;
if (auto m1 = dynamic_cast<Foo*>(a)) {
    if (auto m2 = dynamic_cast<Bar*>(b)) {
        matched = true;
    }
}
if (!matched) {
    // This is because C++ does not allow you to declare two variables inside the condition...
}

I know about the Mach7 library but to be honest it seems awful as you need to write metadata for your structures (also as I've noticed it has quite a lot of bugs and limitations).

Is there a way to make these kind of matches more readable?

Upvotes: 5

Views: 3267

Answers (1)

Hans Olsson
Hans Olsson

Reputation: 12507

The following seems to be a way to avoid the double if for two matches - and can easily be generalized:

template <class T1,class T2> struct castPairstruct : public std::pair<T1,T2> {
     operator bool() {return first && second;}
     castPairstruct<T1,T2>(T1 a,T2 b):std::pair<T1,T2>(a,b) {;}
};

template <class T1,class T2> castPairstruct<T1,T2> castPair(T1 a,T2 b){
    return castPairstruct<T1,T2>(a,b);
}
if (auto j=castPair(dynamic_cast<Foo*>(a),dynamic_cast<Bar*>(b)) {

Upvotes: 1

Related Questions