Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bind pointer to member operators in C++

Tags:

c++

operators

What is the point of them?
I've never used them for anything, and I can't see myself needing to use them at all.
Am I missing something about them or are they pretty much useless?

EDIT: I don't know much about them, so a description about them might be necessary...

like image 788
DeadHead Avatar asked Dec 07 '22 07:12

DeadHead


1 Answers

A PMF (pointer to member function) is like a normal (static) function pointer, except, because non-static member functions require the this object to be specified, the PMF invocation syntax (.* or ->*) allow the this object to be specified (on the left-hand side).

Here's an example of PMFs in use (note the "magic" line with the .* operator being used: (lhs.*opit->second)(...), and the syntax for creating a PMF, &class::func):

#include <complex>
#include <iostream>
#include <map>
#include <stack>
#include <stdexcept>
#include <string>

namespace {
    using std::cin; using std::complex; using std::cout;
    using std::invalid_argument; using std::map; using std::stack;
    using std::string; using std::underflow_error;

    typedef complex<double> complexd;
    typedef complexd& (complexd::*complexd_pmf)(complexd const&);
    typedef map<char, complexd_pmf> opmap;

    template <typename T>
    typename T::reference top(T& st) {
        if (st.empty())
            throw underflow_error("Empty stack");
        return st.top();
    }
}

int
main()
{
    opmap const ops{{'+', &complexd::operator+=},
                    {'-', &complexd::operator-=},
                    {'*', &complexd::operator*=},
                    {'/', &complexd::operator/=}};

    char op;
    complexd val;
    stack<complexd> st;

    while (cin >> op) {
        opmap::const_iterator opit(ops.find(op));
        if (opit != ops.end()) {
            complexd rhs(top(st));
            st.pop();
                                        // For example of ->* syntax:
            complexd& lhs(top(st));     // complexd* lhs(&top(st));
            (lhs.*opit->second)(rhs);   // (lhs->*opit->second)(rhs);
            cout << lhs << '\n';        // cout << *lhs << '\n';
        } else if (cin.unget() && cin >> val) {
            st.push(val);
        } else {
            throw invalid_argument(string("Unknown operator ") += op);
        }
    }
}

[Download]

It's a simple RPN calculator using complex numbers instead of real numbers (mostly because std::complex is a class type with overloaded operators). I've tested this with clang; your mileage may vary with other platforms.

Input should be of the form (0,1). Spaces are optional, but can be added for readability.

like image 136
Chris Jester-Young Avatar answered Dec 25 '22 06:12

Chris Jester-Young