Survey of overloaded arithmetic operators c+++



  • There are shabby classes.

    template< int rows, int columns, typename Type >
    class Matrix : public Tensor<rows*columns, Type> {...}
    

    template< int size, typename Type >
    class Vector : public Tensor<size, Type> {...}

    template< typename Type >
    class Quaternion : public Tensor<4, Type> {...}

    All inherited from the base class chablon:

    template< int elements, typename Type = DEFUALT_TYPE >
    class Tensor {
    Tensor() {...}
    Tensor( const Tensor<elements, Type>& other ) {...}
    ~Tensor() {...}

    template< int elements, typename Type, typename Scalar >
    friend Tensor< elements, Type> operator+( const Tensor< elements, Type>& left, const Scalar right );
    ...
    // overloading operators -,,/,+=,-=,=,/=
    protected:
    Type array[elements];
    }

    Which is primarily responsible for basic arithmetic operations: stocking, subtracting, multiplication, scaloring, because for all inherited types, these operations are the same.

    But the problem is that these operators return the basic class Tensor, which in turn raises some problems:

    1. The result cannot be attributed to the vector and the vector scaling:

      Vector<3,double> vec1;
      Vector<3,doubel> vec2 = vec1+1;
    2. For Matrix classes, Vector, Quaternion is overloaded by a standard withdrawal operator, but this will not work:

      std::cout << vec1+2;
    3. It is not possible to use the result immediately:

      (vec1+5).length();

    Although, it's almost the same as two.

    The first problem could be solved, for example, by creating a copy design for Matrix, Vector, Quaternion, which would create an object from class Tensor:

    Vector( const Tensor<size, Type>& tensor ) : Tensor<size, Type>( tensor ) {...}

    But it doesn't solve the other problems, and it passes a code known to be false:

    Matrix<2,2,double> mat1;
    Vector<4,double> vec1 = mat1+2;

    Now I've solved the problem that I'm redefining these operators for every class I've learned. But first, it's mutton, because for each class, it's about 12 grand. What if we change something? Add a new class? And second, it's the duplicate of the same code.

    How can this problem be resolved more elegantly?



  • You can use a technique known by name. http://scrutator.me/post/2014/06/26/crtp_demystified.aspx ♪ I'll give you an example of how you can accomplish this, and you'll already read your own code:

    #include <iostream>
    

    template<typename T, typename Derived>
    class Base
    {
    public:
    Derived operator+(int scalar)
    {
    //добавим сюда сложение
    return self();
    }
    private:
    Derived
    self()
    {
    return static_cast<Derived*>(this);
    }
    };

    template<typename T>
    class A: public Base<T, A<T>>
    {
    public:
    A() = default;
    A(const A&)
    {
    std::cout << "A copy ctor\n";
    }
    };

    template<typename T>
    class B: public Base<T, B<T>>
    {
    public:
    B() = default;
    B(const B&)
    {
    std::cout << "B copy ctor\n";
    }
    };

    int main(int argc, char* argv[])
    {
    A<int> a;
    B<float> b;
    a = a + 1;
    b = b + 5;

    // Следующие строки не скомпилируются
    //a = b + 1;
    //b = a + 1;
    

    }




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2