Re: error: no matching function for call to `Anton::Anton(Anton)`

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> Don' quite agree with that. But I also don;t have the book in front of me.
> 
> 
> std::cout << "abc" << "xyz";
> 
> The result of the first '<<' is NOT a temporary object. It is a reference to the original object no temporary required. Works fine for me.
>

I was a bit fast here. What I had in mind was to give sort of a typical example where non-const references
to temporary objects are used. I came up with classes used to create and output xml-elements to a stream.
Works like

cout << xml_element("abc").set("field1", "value1").set("field2", "value2");

producing

<abc field1="value1" field2="value2> </abc> 

Here is no need to create a static or an automatic object, a temporary is just fine,
created with xml_element("abc"), which then is modified with the set-methods

xml_element& xml_element::set(string, string) { ...; return *this; }

After processing of the above output-instruction the temporary object is destroyed,
and we are happy. And when overloading operator << for xml_elements, we don't need
to copy xml_elements, but we can use references (non-const if we wish).

(Of course the whole thing is a bit more complicated (but actually not much), since
for need to cater for nesting.)

Now this structurally is the same as output (or input) streaming like

cout << a << b;

only in this example the object passed through the references is not a temporary, but
a static object.

But this is nothing principal: The point here is that it *doesn't matter*, and instead of
cout we could use for example a temporary object of type std::ostringstream.
For example:

std::ostringstream() << "sum = " << 1 + 2 << "\n";

Now since operator << returns a reference to an object of type std::basic_ostream,
it seems we can not do much with such a construction (how to get the string
out of it??), but with other classes (like xml_element) we can make good use
of such constructions.


Perhaps in these examples it is a bit confusing, that the reference to the temporary is only used for
the hidden "this"-argument, or as second argument of an overloaded << (or for the first argument of <<
but without good use).

So a final example, just to use standard functions:

struct Y {
  int n;
  Y& set(int new_n) { n = new_n; return *this; }
  ~Y() { std::cout << "~Y: " << n << "\n"; }
};

int f(Y& y) {
  return y.n++;
}

int main() {
  std::cout << f(Y().set(77)) << "\n";
}

Output is

77
~Y: 78

This is all standard conforming (to the best of
my knowledge).

All clear ?! (Or not???)

Oliver


> 
> -----Original Message-----
> From: Oliver Kullmann [mailto:O.Kullmann@xxxxxxxxxxxxx]
> Sent: Friday, October 10, 2003 2:05 PM
> To: gcc-help@xxxxxxxxxxx
> Subject: Re: error: no matching function for call to
> `Anton::Anton(Anton)`
> 
> 
> Hi,
> 
> although this thread seems to be closed, it seems necessary to me
> to discuss some misunderstandings (as I believe).
> 
> > Hi Eric,
> > 
> > As per section 5.5 of Stroustrup's C++PL (3rd ed or special ed), a temporary object cannot be bound to a non-const reference.
> >
> 
> I don't have the book in my office, but it is not true. Temporary object *can* be bound to non-const
> references: A typical example is streaming via operator <<, that is, in
> 
> std::cout << "abc" << "xyz"; 
> 
> the first call to operator << returns a temporary which is then bound to the
> first argument of operator <<, which is a non-const reference.
> 
> Or to give another example (a simplified version of a class for building up xml-expressions):
> 
> #include <iostream>
> #include <ostream>
> 
> class Nat {
>   int n;
> public :
>   Nat() : n(0) {}
>   Nat& inc() { ++n; }
>   friend inline std::ostream& operator <<(std::ostream& o, Nat x) {
>     o << x.n;
>   }
> };
> 
> int main() {
>   std::cout << Nat().inc().inc().inc() << "\n";
> }
> 
> This is perfectly legal (and the output is "3").
> 
> As one finds it in ISO 14882:1998(E), Section 8.5.3,
> initialisation of references is not primarily concerned
> with constness, but with the distinction between lvalues and 
> rvalues (every expression is either an lvalue or an rvalue).
> The rule about reference binding is as simple (mainly) as follows:
> 
> A non-const reference can be bound only to lvalues,
> while a const reference can be bound to lvalues and rvalues.
> 
> Now functions which return references return lvalues
> ([ISO], Section 5.2.2, point 10),
> while constructors yield rvalues
> ([ISO], Section 5.2.3).
> 
> This explains why in the original example of Eric
> 
> Anton a[] = {Anton()};
> 
> we get an error: only a copy-constructor with a non-const references was
> defined, and since the initialisation of the elements of array a happens
> via the copy constructor, the copy constructor does not accept the rvalue
> Anton().
> 
> But the member function ref() of Anton defined later yields an lvalue, and
> thus
> 
> Anton a[] = {Anton().ref()};
> 
> is no problem. Just as an illustration:
> 
> #include <iostream>
> #include <ostream>
> 
> class Anton {
>   int n;
> public :
>   explicit Anton(int n) : n(n) {}
>   Anton(Anton& a) : n(a.n) {}
>   Anton& ref() { return *this; }
>   friend inline std::ostream& operator <<(std::ostream& o, Anton a) {
>   return o << a.n;
>   }
> };
> 
> int main() {
>   Anton a[] = {Anton(1).ref(), Anton(0) = Anton(2), Anton(3).ref()};
>   std::cout << a[0] << a[1] << a[2] << "\n";
>   // output: 123
> }
> 
> I very much recommend (for several reasons) to read
> 
> @Article{Hyslop2002ObjectfulLifetime,
>   author = 	 {Jim Hyslop},
>   title = 	 {Conversations: It's an Object-ful Lifetime},
>   journal = 	 {C/C++ Users Journal},
>   year = 	 2002,
>   volume =	 20,
>   number =	 12,
>   month =	 {December},
>   note =         {Can be downloaded from \url{http://www.cuj.com/documents/s=7976/cujcexp2012hyslop/}},
>   annote =	 {Vorhanden. Explizite Typ-Konvertierungen geben R-Werte zurueck, Funktionen, die Referenzen zurueckgeben, aber L-Werte. Bezug zu "It's A Wonderful Life".}
> }
> 
> which can be downloaded from the given url, and which discusses the same subject.
> 
> Oliver
> 
> 


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux