3
\$\begingroup\$

This method is taken from Syntactic Aspartame. This is my attempt at a generic version.

The goal is to create an operator X <NAME> Y where name is anything, and X, Y, and the return is of any type.

Here is the 'library':

#ifndef COMPUTERSCIENCE_ANGULAR_OPERATOR_H
#define COMPUTERSCIENCE_ANGULAR_OPERATOR_H

template <typename LHS, typename RHS, typename RET> struct AngularOperator;

template <typename LHS, typename RHS, typename RET>
struct InnerAngularOperator {
    const AngularOperator<LHS, RHS, RET>* outer;
    LHS* lhs;
    bool outer_l;

    RET operator>(RHS& rhs) {
        return (outer_l) ? outer->angular_lr(*lhs, rhs) : outer->angular_rr(*lhs, rhs);
    }

    RET operator<(RHS& rhs) {
        return (outer_l) ? outer->angular_ll(*lhs, rhs) : outer->angular_rl(*lhs, rhs);
    }
};

template <typename LHS, typename RHS, typename RET>
struct AngularOperator {
    explicit AngularOperator() { }

    virtual RET operator()(LHS& lhs, RHS& rhs) const = 0;
    virtual RET angular_lr(LHS& lhs, RHS& rhs) const { return operator()(lhs, rhs); }
    virtual RET angular_rr(LHS& lhs, RHS& rhs) const { return operator()(lhs, rhs); }
    virtual RET angular_ll(LHS& lhs, RHS& rhs) const { return operator()(lhs, rhs); }
    virtual RET angular_rl(LHS& lhs, RHS& rhs) const { return operator()(lhs, rhs); }
};

template <typename LHS, typename RHS, typename RET>
InnerAngularOperator<LHS, RHS, RET> operator<(LHS& lhs, const AngularOperator<LHS, RHS, RET>& outer) {
    return {&outer, &lhs, true};
};

template <typename LHS, typename RHS, typename RET>
InnerAngularOperator<LHS, RHS, RET> operator>(LHS& lhs, const AngularOperator<LHS, RHS, RET>& outer) {
    return {&outer, &lhs, false};
};

#endif //COMPUTERSCIENCE_ANGULAR_OPERATOR_H

And here is a simple implementation for string concatenation:

static const struct OP__ANG__STRING_CONCAT : AngularOperator<std::string, std::string, std::string> {
    std::string operator()(std::string& lhs, std::string& rhs) const override { return lhs + rhs; }
} C{};

And finally the usage of all of this would be:

std::string a = "123", b = "456";
std::string c = a <C> b;
// c == "123456
\$\endgroup\$
1
\$\begingroup\$

I think your approach is problematic, in the following senses:

  • You use inheritance for genericity. There's no good reason for there to be an abstract base class for such operations. The behavior of your class is compile-time-determined by the binary operator you which to represent, and nothing else.
  • You use virtual methods, which really have no bearing on the problem at hand. That is, I don't see any reason why such operators need vtables.
  • You template on the binary operator's parameter and result types, rather than the operator itself, i.e. instead of

    template <typename LHS, typename RHS, typename RET>
    

    try

    template <typename Function>
    

    with std::return_type to obtain RET and so on.

  • Your infix operator implementation has state - and pointer state at that, which is difficult to optimize away - instead of just using temporary values which can get discarded. Don't be so stuck on imperative programming...

I'm pretty sure you could address all three of these issues with a more templated-oriented implementation; with an intermediate class for "infix operator after having gotten the LHS" (or after having gotten the RHS) which can then take the other operator. Possibly the CRTP is relevant here.

I'm being a bit brief and a bit philosophical since I'm strapped for time. If this is too vague for you (=OP), ask for clarification and I'll expand this answer later on.

\$\endgroup\$
  • \$\begingroup\$ I know this is little late, but could you elaborate on the four bullet points. I understand the last one pretty well, but the others are more... shaky. Thanks, Zach. \$\endgroup\$ – Zach Hilman Oct 20 '17 at 0:50
  • \$\begingroup\$ @ZachHilman: Added a few words. \$\endgroup\$ – einpoklum Oct 22 '17 at 18:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.