From: Paul Bibbings on
silentway wrote:
> I am trying to create a simple vector class with overloaded operators
> for assignment, +=, -=, +, *, etc
> My code for the overloaded operators worked OK, until I tried operator+
> ()
> The problem is that I can not return a local variable.

The problem here is not actually that you cannot return a local variable, but
rather that you do not have a copy constructor that can perform the required
copy initialization of F from the value returned by your overload operator+()
(see below).

> This is fair
> enough, but I am sure that this used to work ok 10 years ago, when I
> was using Zortech compiler. I am back to C++ after an outrageously
> long break without doing any codng. I am now using g++ compiler.

I was not seriously coding in C++ 10 years ago and have never used the Zortech
compiler, but as 10 years leaves us still within the time of the C++98 standard,
I very much doubt that any compiler that aimed to be standards-compliant (if
Zortech ever did) would have compiled the code as is.

> class vec
> {
> public:
// <snip>
> vec(vec &rv) : mx(rv.mx) { printf("in copy constr\n"); } // ;
// <snip>
> const vec operator+(const vec &rv);
// <snip>
> };

Here, your copy constructor takes its argument by non-const reference, whereas
the return value from your overloaded op+ is a const rvalue which will fail to
bind on both counts.

<snip>

> int main () {
> vec A(0.5); A.print("A:");
> vec B(0.1); B.print("B:");
// <snip>
> // vec F = A + B; // problem!!
> //error: no matching function for call to 'vec::vec(vec)'
> return 0;
> }

(From your code as given, I would have expected the error message to have been
error: no matching function for call to 'vec::vec(const vec)'.
Removing the const from the return value of your op+ would be needed to produce
the error you give here.)

> The class and test code works OK except for the line
> vec F = A + B;

In this line we have a call to your op+ followed by copy initialization of F.
There must be a valid copy constructor that can handle the result of op+ in
order to perform the initialization (even where the compiler might choose to
elide it). As mentioned, your op+ returns a const rvalue, whereas your copy
constructor as given is looking for a non-const lvalue. Removing the const from
the return value of op+ is not sufficient, as we still have an rvalue which will
not bind to the non-const reference of your copy constructor. What you need is:

vec::vec(const vec& rv);

> The error message is
> error: no matching function for call to 'vec::vec<const vec>'
>
> I have seen lots of examples that use the above code (or similar), but
> they don't seem to work for me
> I am starting to suspect that gcc / g++ does not support something
> here, but that sounds too crazy

gcc is doing fine! ;-)

Regards

Paul Bibbings

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Torsten Robitzki on
silentway schrieb:
> // vec F = A + B; // problem!!
> //error: no matching function for call to 'vec::vec(vec)'

<snip>
> Can someone point me in the right direction?

I hope so. The problem is you copy contructor taking a refernce to not
const vec. The term A + B creates a temporary and a temporary can't be
bound to a reference to not const vec.

vec(const vec &rv) : mx(rv.mx) { printf("in copy constr\n"); };
^^^^^

will solve the problem.

Btw. the usual implementation of operator+ would be a free function and
be implemented in terms of operator+=

best regards
Torsten

--
kostenlose Wirtschaftssimulation: http://www.financial-rumors.de

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Neil Butterworth on
silentway wrote:

My comments are inline with te code:


> #include <iostream>

Your use of printf() (why not use iostreams?) eans that you should
include the header it s declared in:

#include <cstdio>

>
> class vec
> {
> public:
> vec(float x = 0.0) : mx(x) { printf("in constructor\n"); };
> vec(vec &rv) : mx(rv.mx) { printf("in copy constr\n"); };

This is your main problem. A copy constructor should take a const
reference as it's parameter - you want:

vec( const vec &rv) : mx(rv.mx) { printf("in copy constr\n"); };


> virtual ~vec() {};
> void setx(float x) {mx = x;};
> vec & operator=(const vec &rv);
> vec & operator+=(const vec &rv);
> const vec operator+(const vec &A) /*const*/;
> void print(char *msg);
> private:
> float mx;
> };
>
> vec & vec::operator=(const vec &rv) {
> printf("in vec & vec::operator=(const vec &rv)\n");
> if (this != &rv)
> mx = rv.mx;
> return *this;
> }
>
> vec & vec::operator+=(const vec &rv) {
> printf("in vec & vec::operator=(const vec &rv)\n");
> mx += rv.mx;
> return *this;
> }
>
> // this compiles ok, but produces error if overloaded + is used in
> code
> const vec vec::operator+(const vec &A) /*const*/ {
> printf("in vec vec::operator+(const vec &A)\n");
> vec result(*this);
> result += A;
> return result;
> }

There is no need for the return value of this method to be const. Also,
operator + is normally implemented as a free function, not a member, to
allow conversion of the LHS operand.

> void vec::print(char *msg) {
> printf("%s %f\n", msg, mx);
> }

Once again, why printf instead of iostreams?

> int main () {
> vec A(0.5); A.print("A:");
> vec B(0.1); B.print("B:");
> vec C(B); C.print("C:");
> vec D = A; D.print("D:");
> vec E; E.print("E:");
> E = A; E.print("E:");
> B += A; B.print("B:");
> // vec F = A + B; // problem!!
> //error: no matching function for call to 'vec::vec(vec)'

Fixed by making the copy ctor take a const reference, so it can bind to
the const value returned by operator+

> return 0;
> }
>
> The class and test code works OK except for the line
> vec F = A + B;
>
> I am compiling from the command line as follows
> g++ -g vec.cpp -o vec -lm
>
> The error message is
> error: no matching function for call to 'vec::vec<const vec>'
>
> I have seen lots of examples that use the above code (or similar), but
> they don't seem to work for me
> I am starting to suspect that gcc / g++ does not support something
> here, but that sounds too crazy

Always, always suspect your own code rather than a compiler bug.

Neil Butterworth

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Matthew Collett on
In article
<bea3b28d-235b-4b0d-8421-9fef3ecb8272(a)a31g2000yqn.googlegroups.com>,
silentway <andybolsover(a)yahoo.co.uk> wrote:

> I am trying to create a simple vector class with overloaded operators
> for assignment, +=, -=, +, *, etc
> My code for the overloaded operators worked OK, until I tried operator+
> ()
....
> Here is my code
>
> #include <iostream>
>
> class vec
> {
> public:
> vec(float x = 0.0) : mx(x) { printf("in constructor\n"); };
> vec(vec &rv) : mx(rv.mx) { printf("in copy constr\n"); };

And here is your problem. Your copy constructor should take its
argument by constant reference:
vec(const vec &rv) : mx(rv.mx) { printf("in copy constr\n"); };

Currently you cannot copy const objects, and so the compiler complains
about a missing copy constructor.

Best wishes,
Matthew

--
http://homepages.ihug.co.nz/~m_collett

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Ulrich Eckhardt on
silentway wrote:
> I am trying to create a simple vector class with overloaded operators
> for assignment, +=, -=, +, *, etc
> My code for the overloaded operators worked OK, until I tried
> operator+(). The problem is that I can not return a local variable.

Huh?

> This is fair enough, but I am sure that this used to work ok
> 10 years ago, when I was using Zortech compiler. I am back to
> C++ after an outrageously long break without doing any codng.

Get a good book. Many things changed.

> #include <iostream>
>
> class vec
> {
> public:
> vec(float x = 0.0) : mx(x) { printf("in constructor\n"); };
> vec(vec &rv) : mx(rv.mx) { printf("in copy constr\n"); };
> virtual ~vec() {};
> void setx(float x) {mx = x;};
> vec & operator=(const vec &rv);
> vec & operator+=(const vec &rv);
> const vec operator+(const vec &A) /*const*/;
> void print(char *msg);
> private:
> float mx;
> };

Several things here:
1. Make one-argument constructor 'explicit' to avoid accidental
construction.
2. Do not create a virtual destructor for objects you don't plan to use
polymorphically.
3. You #include <iostream> but use printf() for which you didn't include any
header.
4. What is print()? Why does it take a pointer to a non-const char? What
does it to the memory pointed to by it?
5. Do not blindly terminate lines with a semicolon. You don't need them
after the definition of a function. I consider it a quirk, but it is
actually allowed in the standard when defining a function as part of the
class definition, but not outside.
6. Your copy-constructor takes a reference to a non-const object. This is
most surely wrong and this oversight is also causing you problems.


> const vec vec::operator+(const vec &A) /*const*/ {
> printf("in vec vec::operator+(const vec &A)\n");
> vec result(*this);
> result += A;
> return result;
> }

The copy-constructor that doesn't take a reference to const is what breaks
this. When fixed, you could also make the operator const. However, there is
another thing you should know, and that is that operators don't have to be
defined as memberfunctions:

vec operator+(vec const& v1, vec const& v2) {
vec res(v1);
res += v2;
return res;
}

This is the typical implementation for operator+ based on operator+=, which
needs to remain inside the class. Note that you can also overload a free
operator for the combination vec/float or float/vec, which wouldn't work for
a bound one.


> g++ -g vec.cpp -o vec -lm

Add -Wall

Uli


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]