I want to create a collection of classes that behave like math vectors, so that multiplying an object by a scalar multiplies each field by that ammount, etc. The thing is that I want the fields to have actual names, instead of being treated as an index.
My original idea to implement this was creating a base class Rn with the overloads and then create derived classes with the pretty names. Something like this:
#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 of of the operators that requires 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 the overloading functions deal with Base objects that can't be converted to Derived ones, so I can't use them in the derived class. However, I can't come up with a solution. Is there a way around this or should I use a totally different approach?
Bonus question: is there some way that I can use std::valarray to keep from having to type lots and lots of operator overloads?
Your Base operators (* in this case) can accept Derived object, but they return a Base, which can't be used as a right-hand operand in Derived default assignment operator. Easiest way to fix this is just add an assignment operator to Derive that will take a Base:
Derived& operator= (const Base<2>& other)
You will have to add it to any derived class, but the implementation is rather straightforward (you can have a void CopyOtherBase function in Base that will do the copy, and have all operator= call it and return *this).
I'll only address the technical difficulty, not whether this is a good idea or not.
The problem is that the result of operator* of Derived is a Base, and operator= of Derived (which is a default operator=) doesn't know how to "eat" a Base.
A simple solution is to create a constructor of Derived that gets a Base, and does whatever is needed to initialize itself correctly. This would allow an on-the-fly conversion of a Base to a Derived - and would work for all other operators of Derived that expect a Base.
Something along the lines of -
Derived(const Base<2>& B) : Base<2>( B )
{
}
I think you're going to be much better off using an enum or static constants to name your fields
e.g., static const int FIELD_NAME = 0;
Static const int FIELD_NAME2 = 1;
than doing this as different types (templates). Then you can go for std::valarray or boost::ublas::vector/matrix types to leverage existing code & get quality performance vector operations to boot.
Template metaprogramming had an interesting idea on solving just this sort of issue with math vectors, but perhaps doesn't solve your issue of naming the parts.
David Abrahams, Aleksey Gurtovoy: C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond, Addison-Wesley, ISBN 0-321-22725-5
According to MSDN,
All overloaded operators except
assignment (operator=) are inherited
by derived classes.
Could this be your problem?
Related
I'm currently investigating the interplay between polymorphic types and assignment operations. My main concern is whether or not someone might try assigning the value of a base class to an object of a derived class, which would cause problems.
From this answer I learned that the assignment operator of the base class is always hidden by the implicitely defined assignment operator of the derived class. So for assignment to a simple variable, incorrect types will cause compiler errors. However, this is not true if the assignment occurs via a reference:
class A { public: int a; };
class B : public A { public: int b; };
int main() {
A a; a.a = 1;
B b; b.a = 2; b.b = 3;
// b = a; // good: won't compile
A& c = b;
c = a; // bad: inconcistent assignment
return b.a*10 + b.b; // returns 13
}
This form of assignment would likely lead to inconcistent object state, however there is no compiler warning and the code looks non-evil to me at first glance.
Is there any established idiom to detect such issues?
I guess I only can hope for run-time detection, throwing an exception if I find such an invalid assignment. The best approach I can think of just now is a user-defined assigment operator in the base class, which uses run-time type information to ensure that this is actually a pointer to an instance of base, not to a derived class, and then does a manual member-by-member copy. This sounds like a lot of overhead, and severely impact code readability. Is there something easier?
Edit: Since the applicability of some approaches seems to depend on what I want to do, here are some details.
I have two mathematical concepts, say ring and field. Every field is a ring, but not conversely. There are several implementations for each, and they share common base classes, namely AbstractRing and AbstractField, the latter derived from the former. Now I try to implement easy-to-write by-reference semantics based on std::shared_ptr. So my Ring class contains a std::shared_ptr<AbstractRing> holding its implementation, and a bunch of methods forwarding to that. I'd like to write Field as inheriting from Ring so I don't have to repeat those methods. The methods specific to a field would simply cast the pointer to AbstractField, and I'd like to do that cast statically. I can ensure that the pointer is actually an AbstractField at construction, but I'm worried that someone will assign a Ring to a Ring& which is actually a Field, thus breaking my assumed invariant about the contained shared pointer.
Since the assignment to a downcast type reference can't be detected at compile time I would suggest a dynamic solution. It's an unusual case and I'd usually be against this, but using a virtual assignment operator might be required.
class Ring {
virtual Ring& operator = ( const Ring& ring ) {
/* Do ring assignment stuff. */
return *this;
}
};
class Field {
virtual Ring& operator = ( const Ring& ring ) {
/* Trying to assign a Ring to a Field. */
throw someTypeError();
}
virtual Field& operator = ( const Field& field ) {
/* Allow assignment of complete fields. */
return *this;
}
};
This is probably the most sensible approach.
An alternative may be to create a template class for references that can keep track of this and simply forbid the usage of basic pointers * and references &. A templated solution may be trickier to implement correctly but would allow static typechecking that forbids the downcast. Here's a basic version that at least for me correctly gives a compilation error with "noDerivs( b )" being the origin of the error, using GCC 4.8 and the -std=c++11 flag (for static_assert).
#include <type_traits>
template<class T>
struct CompleteRef {
T& ref;
template<class S>
CompleteRef( S& ref ) : ref( ref ) {
static_assert( std::is_same<T,S>::value, "Downcasting not allowed" );
}
T& get() const { return ref; }
};
class A { int a; };
class B : public A { int b; };
void noDerivs( CompleteRef<A> a_ref ) {
A& a = a_ref.get();
}
int main() {
A a;
B b;
noDerivs( a );
noDerivs( b );
return 0;
}
This specific template can still be fooled if the user first creates a reference of his own and passes that as an argument. In the end, guarding your users from doing stupid things is an hopeless endeavor. Sometimes all you can do is give a fair warning and present a detailed best-practice documentation.
Suppose I have a class called Complex with 2 parameters real and imag. I want to overload the =(assignment) operator so that I could copy the value from the real parameter and assign it to an int.
If my main would look something like;
Complex z(1, 2);
int a = z;
I want a to be equal to 1.
How can I implement this function/method?
Use cast operator:
//Declaraion
class Complex {
operator int();
}
//Definition
Complex::operator int() {
return real_number;
}
Cast operator can implicitly convert a class instance to a certain type that is defined. It is a handy tool, but sometimes can be dangerous and vulnerable, and hard to debug.
When you define the assignment operator you are instructing the compiler on what to do when a value of possibly a different type is assigned to and instance of your class.
In this case instead you want to define what to do when an instance of your class is assigned to a variable of a different non-class type and this is not possible however. In other words it's the receiving instance that defines what to do in case of an assignment and you can customize this only for class types.
Something quite similar is instead to define how an instance of your class should be convertible to another type, e.g. how to convert a complex to an integer, and this conversion will be used also in case of assignment:
struct complex {
double real, imag;
...
operator int () const { return int(real); }
};
It isn't ideal to have code that reads as an assignment of types from different equivalence classes. It is correct that one should use casting instead, but the casting must be made explicit in C++11:
struct Complex {
double r, i;
...
explicit operator int () const { return int(r); }
};
Complex c = { 1.1, 2.2 };
float a = c; // fails with explicit
float a = (float)c; // fails with explicit
int a = c; // fails with explicit
int a = (int)c; // compiles with explicit
Do you really need to define a class for complex? It's part of standard library
Even you can see <complex> (#include <complex>) to find the operators and definitions overloaded
See more here
Hi I am trying to do operator overloading for +(addition) operator to add my user defined datatype objects .
Following is the code for that.
#include <iostream>
using namespace std;
class complex {
int i;
double f;
public:
complex(int ii=0,double ff=0){
i = ii;
f = ff;
}
complex operator+(complex object) {
complex result;
result.i = this->i + object.i;
result.f = this->f + object.f;
return result;
}
void display() {
cout << i <<"\t"<< f;
cout << endl;
}
};
int main(){
complex obj1(1,1.1),obj2(2,2.2),obj3;
int i(5);
obj3 = obj1 + obj2;
obj3.display();
obj3 = obj3 + i;
obj3.display();
obj3 = i + obj3;//generates me compiler error
obj3.display();
return 0;
}
I have learnt that when I do obj1 + obj2,it is expanded by the compiler as obj1.operator+(obj2);
So that part of code works fine.
But when I do add an int and complex ,I think it get expanded as i.operator(obj1).
So it gives me compiler errors.
Should I define operator+ function in int class or how to solve this?
Please suggest,
Thank you,
You will have to provide an overloaded version of + which takes int and class complex object as input parameters. This function should be a non member function.
complex operator+(int i, complex object)
Note that additionally, if you want to access protected or private members inside this overloaded function then it will have to be made friend of your complex class.
This is a peculiar example of the strength of free functions used for operator overloading as against member function operator overloads.
This is the reason why the operator+ is usually defined as a free function: instead of having complex complex::operator+(complex object), you could (should) define a free function
complex operator+(const & complex lhs, const & complex rhs)
{
return complex(lhs.i + rhs.i, lhs.j + rhs.j);
// You will need some way to access i and j, either by making this function
// a friend of complex or by providing getters
}
This way, the line obj3 = i + obj3 will be equivalent to operator+(i, obj3); since an integer can be converted to a complex thanks to the constructor you wrote, the call will succeed and be equivalent to this one: operator+(complex(i), obj3).
As a rule of thumb, you should prefer free functions over member functions to overload binary operators when the left hand side and the right hand size have equal importance. This way, you know that if a op b works then b op a will work too.
On a sidenote, you should also prefer passing your parameters as reference-to-const, and mark your member functions as const when they are (like operator+ and display in your sample).
Define a function outside any class:
complex operator + (int lhs, complex rhs) { /* ... */ }
Make sure the compiler can see it, and you can add ints to complexes to your heart's content. You probably also want one with the parameters the other way around.
I've run into an issue I don't understand and I was hoping someone here might provide some insight. The simplified code is as follows (original code was a custom queue/queue-iterator implementation):
class B
{
public:
B() {};
class C
{
public:
int get();
C(B&b) : b(b){};
private:
B& b;
};
public:
C get_c() { return C(*this); }
};
int main()
{
B b;
B::C c = b.get_c();
c = b.get_c();
return EXIT_SUCCESS;
}
This, when compiled, gives me the following error:
foo.cpp: In member function 'B::C& B::C::operator=(const B::C&)':
foo.cpp:46: error: non-static reference member 'B& B::C::b', can't use default assignment operator
foo.cpp: In function 'int main()':
foo.cpp:63: note: synthesized method 'B::C& B::C::operator=(const B::C&)' first required here
I can go around this by using two separate C variables, as they are supposed to be independent 'C' objects, but this only hides the problem (I still don't understand why I can't do this).
I think the reason is that the reference cannot be copied, but I don't understand why. Do I need to provide my own assignment operator and copy constructor?
This problem has nothing to do with inner classes. In C++ you just can't (re)assign references - they need to be initialised when defined.
A simpler example is:
class B
{
public:
B(int& i) : ir(i) {};
int& ir;
};
int main()
{
int i;
B b(i); // Constructor - OK
int j;
B bb = B(j); // Copy constructor - OK
bb = b; // Assignment - Error
return 0;
}
A reference cannot be changed after being given its initial value. This means that it is impossible to write an assignment operator that changes the value of a reference member. If you need to do this, use a pointer instead of a reference.
Actually, there's a solution to this. You can implement operator= in terms of copy construction, and it will work :) It's a very capable technique for such cases. Assuming you do want to support assignment.
C++ doesn't have "inner classes", just nested class declarations. "inner classes" are a Java-ism that I don't think are found in other mainstream languages. In Java, inner classes are special because they contain an implicit immutable reference to an object of the containing type. To achieve the equivalent to C++'s nested declarations in Java requires use of static inner classes; static inner classes do not contain a reference to an object of the declaring type.
Is it possible to inherit identically named operator which only differ in return type, from two different abstract classes.
If so, them:
what is the syntax for implementing operators
what is the syntax for using/resolving operators
what is the overhead in general case, same as for any other virtual function?
if you can provide me with a reference or sample code that would be helpful
thanks
12struct abstract_matrix {
13 virtual double& operator()(int i, int j);
14};
15
16 struct abstract_block_matrix {
17 virtual double* operator()(int i, int j);
18 };
19
20struct block_matrix : abstract_matrix, abstract_block_matrix {
21
22};
block matrix needs to provide implementations for both operators, so that it is either a matrix or a block matrix, depending on the context. I do not know how to provide implementation specific to block_matrix class.
right now, it is done by passing object wrapped type as the last argument, but that does not seem very clean. I would like to retain pure matrix notation.
The return type of a function is not part of it's signature, so you can't have two operator+(i,j)'s in block_matrix - that would be an ambiguous call. So multiple inheritance is sort of a red herring here on this point. You just can't do that.
What are you really trying to do, and why?
In any event, for your other question: virtual operators are exactly like virtual functions in terms of performance and the way they operate. There are just slight semantic differences in how you use them - but under the hood they're just functions like any other.
You can't overload on the return type. When a function or an operator is invoked the compiler has to know which one to call. It will not infer that based on what the function(operator) call assigned to.
Looks like your are looking to implement some matrix math. Perhaps if you download DirectX SDK or OpenGL and have a look how they do it, you might get some ideas on how to do it properly.
I got it work, but it's wonky. I do love templates.
template<class T>
class Base1
{
};
template<class T>
class Base2
{
};
class Derived;
template<>
class Base1<Derived>
{
public:
double foo(){return 0.1;}
};
template<>
class Base2<Derived>
{
public:
int foo(){return 1;}
};
class Derived
: public Base1<Derived>
, public Base2<Derived>
{
public:
using Base1<Derived>::foo;
};
int main()
{
double sum = 0;
Derived d;
sum += d.foo(); //+ .1
Base1<Derived> * pI = &d;
sum += pI->foo(); //+ .1
Base2<Derived> * pF = &d;
sum += pF->foo(); //+ 1
return (sum*10);
}
I couldn't get it to work without templates, although it seems like it should be able to. I'm not sure if you can get away with just doing templated member functions in the same manner, but my gut says "no".
In terms of code organization, I would then define the Base# stuff right after the definition or declaration of Derived, since that's really what it's for. Keep in mind you can then use typename Base1<Derived> something to make things prettier.
Edit:
Oh, right! It doesn't allow you to do the "using" trick or have different return types, but it's otherwise simpler:
class Derived
: public Base1
, public Base2
{
double Base1::foo(){...}
double Base2::foo(){...}
}
There may be a terrible, horrible, awesome way to combine these two approaches, but I don't think it'll actually help out when using the code. I may get back to you on that.