This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: error: no matching function for call to `Anton::Anton(Anton)`
- From: Oliver Kullmann <O dot Kullmann at Swansea dot ac dot uk>
- To: Martin York <martin dot york at veritas dot com>, gcc-help at gcc dot gnu dot org
- Date: Sat, 11 Oct 2003 15:03:55 +0100
- Subject: Re: error: no matching function for call to `Anton::Anton(Anton)`
- References: <305FFEDE10E368449714750CCC448E1218E46F@rosxchcln1.enterprise.veritas.com>
> 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@Swansea.ac.uk]
> Sent: Friday, October 10, 2003 2:05 PM
> To: gcc-help@gcc.gnu.org
> 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
>
>