Conclusion from a class with operator overloading

I want to create a collection of classes that behave like mathematical vectors, so multiplying an object by a scalar multiplies each field by that number, etc. The thing is, I want the fields to have actual names, and not be treated as an index.

My initial idea to implement this is to create an Rn base class with overloads, and then create derived classes with nice names. Something like that:

#include <iostream> #include <algorithm> using namespace std; template<int N, class X=double> struct Base{ X xs[N]; Base(){}; Base(X *data){ copy(data, data+N, xs); } Base operator*= (double d){ for(int i=0; i<N; i++){ xs[i] *= d; } return *this; } Base operator* (double d){ Base answer = *this; answer *= d; return answer; } //also operators for +=, +, multiplication from left, maybe [] too }; struct Derived : public Base<2>{ Derived(double a, double b){ foo() = a; bar() = b; } double &foo(){ return xs[0]; } double &bar(){ return xs[1]; } }; int main() { //this is OK: double data[2] = {0.0, 2.0}; Base<2> b(data); b = b*17.0; cout << b.xs[0] << endl; //I can't do this: Derived x(0.0, 2.0); x = x*17.0; cout << x.foo() << endl; return 0; } 

I get a compiler error whenever I try to use statements that require copying. gcc gave me the following compiler error:

 teste.cpp: In function 'int main()': teste.cpp:52: error: no match for 'operator=' in 'x = x.Derived::<anonymous>.Base<N, X>::operator* [with int N = 2, X = double](1.7e+1)' teste.cpp:31: note: candidates are: Derived& Derived::operator=(const Derived&) 

I think the problem is that overload functions deal with basic objects that cannot be converted to derivatives, so I cannot use them in a derived class. However, I cannot find a solution. Is there a way around this or should I use a completely different approach?

Bonus question: is there a way I can use std :: valarray so as not to print many, many operator overloads?

+2
source share
5 answers

I will only consider technical difficulties, and not a good idea or not.

The problem is that the result of the * Derived operator is the base, and the = operator of Derived (which is the default = operator) does not know how to "eat" the base.

A simple solution is to create a Derived constructor that receives the base and does everything necessary for proper initialization. This would allow transforming the Base into a derivative on the fly and would work for all other Derived operators that expect Base.

Something along the lines -

 Derived(const Base<2>& B) : Base<2>( B ) { } 
+2
source

Your base operators (* in this case) can accept a Derived object, but they return a base that cannot be used as the right operand in the default assignment operator Derived. The easiest way to fix this is to simply add the Derive assignment operator, which will occupy the base:

 Derived& operator= (const Base<2>& other) 

You will need to add it to any derived class, but the implementation is quite simple (you can have a Void CopyOtherBase function in the database that will make a copy and have all operator = call it and return * this).

+3
source

I think you will be much better off using enum or static constants to name your fields

for example, static const int FIELD_NAME = 0;
Static const int FIELD_NAME2 = 1;

how to do it as different types (templates). Then you can go to std :: valarray or boost :: ublas :: vector / matrix types to use existing code and get quality vector actions to load.

+1
source

The metaprogramming of the templates had an interesting idea about solving precisely these kinds of problems with mathematical vectors, but perhaps it did not solve your problem of naming parts.

David Abrahams, Alexey Gurtovoy: C ++ Template Metaprogramming: concepts, tools and methods from Boost and Beyond, Addison-Wesley, ISBN 0-321-22725-5

0
source

According to MSDN ,

All overloaded operators, except assignment (operator =), are inherited by derived classes.

Could this be your problem?

0
source

Source: https://habr.com/ru/post/1382731/


All Articles