Question

Is it possible to have a non-member operator like

bool operator==(const std::string &l, const Token r)

as a private member function of an unrelated class Interpreter? I tried it the obvious way, but it doesn't work (too many arguments). I know, already the title "non-member function [...] as member" says the opposite, but is there a better way than a function

bool isToken(const std::string &l, const Token r)

to make a comparison which is dependant on a (non-static) member of Interpreter?

It isn't possible to compare Tokens to strings outside of an Interpreter.

Some further information: Token is an enum and the comparisation is dependant on the language set on construction of an Interpreter.

Was it helpful?

Solution

It is not possible to make a version of operator == the way you want. It can't be made static. If it is a member, then it must take one argument.

If you are willing to "duplicate code", then you can play tricks with namespaces. Your generic interpreter could be a template that takes a language specific derived class as a template parameter. It in turn calls a templated operator== based on a language specific token.

template <typename TOKEN>
bool operator == (const std::string &l, const TOKEN token) {
    return token == l;
}

// Language specific interpreters inherit from this template
template <typename LANG>
class Interpreter {
public:
    void interpret () {
        std::string s("hi");
        if (s == LANG::KEYWORD_ELSE) {}
    }
};

Each language specific subclass of Interpreter lies in a language specific namespace. The implementation repeats enumerations of the keywords, but otherwise defers to the template implementation.

namespace Lang0 {
    class Interpreter : public ::Interpreter<Lang0::Interpreter> {
        //...
    public:
        enum Token { KEYWORD_ELSE, //...
                   };
        static Interpreter & instance () {
            static Interpreter interpreter;
            return interpreter;
        }
    };
}

namespace Lang1 {
    class Interpreter : public ::Interpreter<Lang1::Interpreter> {
        //...
    public:
        enum Token { KEYWORD_ELSE, //...
                   };
        static Interpreter & instance () {
            static Interpreter interpreter;
            return interpreter;
        }
    };
}

Each namespace also provides a language specific implementation for operator== to compare a string to the language specific token.

namespace Lang0 {
    bool operator == (const Interpreter::Token token, const std::string &l) {
        //...
    }
}

namespace Lang1 {
    bool operator == (const Interpreter::Token token, const std::string &l) {
        //...
    }
}

Then, when the template implementation of Interpreter calls the template version of operator==, it resolves to the language specific implementation in the respective language specific namespace.

OTHER TIPS

Since comparison is made by a non-static member of Interpreter (say, is_equal()), you need three objects to make a comparison: an Interpreter, a string, and a Token.

If you know there is exactly one valid Interpreter object instance at the time of comparison, you could have this instance made accessible statically, e.g.

bool operator==(const std::string &l, const Token r)
{
   return Interpreter::instance().is_equal(l, r);
}

where static member instance() returns the Interpreter object that does the work.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top