PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Thursday, July 7, 2022

[FIXED] How to merge different operators with the same logic in C++ class for not copypasting

 July 07, 2022     c++, c++11, c++17, class, operator-overloading     No comments   

Issue

Is it possible to merge some operators of class that have same logic but different operators to not copypasting. For example, I have class with operators +=, -=:

class Matrix {
public:
    Functor& operator+=(const Functor& rhs) {
        for (int i = 0; i < num; ++i) {
            v[i][j] += rhs.v[i][j];
        }
        return *this;
    }

    Functor& operator-=(const Functor& rhs) {
        for (int i = 0; i < num; ++i) {
            v[i][j] -= rhs.v[i][j];
        }
        return *this;
    }

private:
    int rows_ {};
    int columns_ {};
    std::vector<std::vector<double>> matrix_;
};

Does C++ has something like:

Functor& operator(+=, -=)(const Functor& rhs) {
        for (int i = 0; i < num; ++i) {
            v[i][j] (+=, -=) rhs.v[i][j];
        }
        return *this;
    }

Solution

You can do it by passing a lambda to a common implementation:

class Matrix {
private:
    template<typename Op>
    Functor& opImpl(const Functor& rhs, Op op) {
        for (int i = 0; i < rows_; ++i) {
          for (int j = 0; j < columns_; ++j) {
            Op(v[i][j], rhs.v[i][j]);
          }
        }
        return *this;
    }

public:
    Functor& operator+=(const Functor& rhs) {
        return opImpl(rhs, [&](double& l, const double r) { r += l; });
    }

    Functor& operator-=(const Functor& rhs) {
        return opImpl(rhs, [&](double& l, const double r) { r -= l; });
    }

private:
    int rows_ {};
    int columns_ {};
    std::vector<std::vector<double>> matrix_;
};

Normally, you'd first implement operator+ and operator- and implement operator+= and operator-= in terms of the former. In that case, you can use std::plus<double>() and std::minus<double>() for the lambda if you're in c++14 or later (thx @StoryTeller).

You can further save space by either having the operators in a base class, having it as using from a namespace or simply by a macro:

#define IMPLEMENT_OP(RET, OP, ARG, T) \
   RET operator ## OP ## (ARG rhs) { \
      return opImpl(rhs, T::operator ## op); \
   }

Another way to solve this - still by delegating - is to use constexpr if:

class Matrix {
private:
    template<char op1, char op2 = ' '>
    Functor& opImpl(const Functor& rhs) {
        for (int i = 0; i < rows_; ++i) {
          for (int j = 0; j < columns_; ++j) {
            if constexpr (op1 == '+' && op2 == '=') {
                v[i][j] += rhs.v[i][j];
            }
            if constexpr (op1 == '-' && op2 == '-') {
                v[i][j] -= rhs.v[i][j];
            }
            // TODO: further ops, error handling here
          }
        }
        return *this;
    }

public:
    Functor& operator+=(const Functor& rhs) {
        return opImpl<'+', '='>(rhs);
    }

    Functor& operator-=(const Functor& rhs) {
        return opImpl<'-', '='>(rhs);
    }

private:
    int rows_ {};
    int columns_ {};
    std::vector<std::vector<double>> matrix_;
};


Answered By - lorro
Answer Checked By - Candace Johnson (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing