C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Re: Template argument passed by reference
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Thomas Mang
Guest





PostPosted: Sat Dec 27, 2003 3:36 pm    Post subject: Re: Template argument passed by reference Reply with quote





Olivier Brunet schrieb:

Quote:
Does anyone know why the following code compile on VS.NET 2003, and fails on
gcc 3.3.2 with this error:

bash-2.05b$ gcc test.cpp
test.cpp: Dans function ‹ int main() ›:
test.cpp:22: error: no matching function for call to `A::test(std::string)'
test.cpp:7: error: candidates are: void A::test(std::string&)

-----------------------------------------------------------------------
#include using std::string;

class A
{
public:
void test(string &a);
};

class B
{
public:
string test2();
};

int main()
{
A a;
B b;

a.test(b.test2());

return 0;
}

seems like a VC 2003 bug, please report it.

You try to pass a temporary object to a reference to non-const which is illegal.

Solution is to change the signature of A::test to "void test(string const &a)"
(note : const reference), or to create an lvalue string which you pass to
A::test, in which case main should read:

int main()
{
A a;
B b;

string lvalue = b.test2();
a.test(lvalue);

return 0;
}


hope that helps,


Thomas


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

Back to top
Conrad Weyns
Guest





PostPosted: Sat Dec 27, 2003 3:38 pm    Post subject: Re: Template argument passed by reference Reply with quote




"Olivier Brunet" <news.2.obrunet (AT) spamgourmet (DOT) com> wrote

Quote:
Does anyone know why the following code compile on VS.NET 2003, and fails
on
gcc 3.3.2 with this error:

bash-2.05b$ gcc test.cpp
test.cpp: Dans function â?¹ int main() â?º:
test.cpp:22: error: no matching function for call to
`A::test(std::string)'
test.cpp:7: error: candidates are: void A::test(std::string&)

-----------------------------------------------------------------------
#include using std::string;

class A
{
public:
void test(string &a);

Note: non const &

Quote:
};

class B
{
public:
string test2();
};


int main()
{
A a;
B b;

a.test(b.test2());

b.test2() return a temp string. It cannot be bound to a non const&.
Alltough ms vc7 .net has become more compliant, you actually have to make
the effort first yourself - amuses me somewhat. Try turning off "Language
Extensions" in the project's c/c++ Language settings and my guess vc7 will
output an error. In other words, say Yes to "Disable Language Extensions"
Smile
With some luck, you wan't be including system header files that need it,
like PlatformSDKIncludeWinNT.h. If so, you loose anyway....

Conrad Weyns

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

Back to top
Francis Glassborow
Guest





PostPosted: Sat Dec 27, 2003 3:48 pm    Post subject: Re: Template argument passed by reference Reply with quote



In message <3fecd73a$0$29064$636a55ce (AT) news (DOT) free.fr>, Olivier Brunet
<news.2.obrunet (AT) spamgourmet (DOT) com> writes
Quote:
Does anyone know why the following code compile on VS.NET 2003, and fails on
gcc 3.3.2 with this error:


GCC is correct, but VC++ may be applying an extension (which it is fully
entitled to do -- even in strictly conforming mode as long as it first
gives a diagnostic)

Quote:
bash-2.05b$ gcc test.cpp
test.cpp: Dans function ‹ int main() ›:
test.cpp:22: error: no matching function for call to `A::test(std::string)'
test.cpp:7: error: candidates are: void A::test(std::string&)

Not a particularly helpful error message.
Quote:

-----------------------------------------------------------------------
#include using std::string;

class A
{
public:
void test(string &a);
};

class B
{
public:
string test2();
};


int main()
{
A a;
B b;

a.test(b.test2());

B::test2() returns a string by value, i.e. a temporary.
A::test has a plain reference to string parameter that may not bind to a
temporary. Change that to string const & and both compilers will be
happy as long as you do not try to change the argument in the body of
A::test().

--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
or http://www.robinton.demon.co.uk
Happy Xmas, Hanukkah, Yuletide, Winter/Summer Solstice to all.


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

Back to top
Dhruv
Guest





PostPosted: Sun Dec 28, 2003 10:06 am    Post subject: Re: Template argument passed by reference Reply with quote

On Sat, 27 Dec 2003 06:09:03 -0500, Olivier Brunet wrote:

Quote:
Does anyone know why the following code compile on VS.NET 2003, and fails on
gcc 3.3.2 with this error:

bash-2.05b$ gcc test.cpp
test.cpp: Dans function ‹ int main() ›:
test.cpp:22: error: no matching function for call to `A::test(std::string)'
test.cpp:7: error: candidates are: void A::test(std::string&)

-----------------------------------------------------------------------
#include using std::string;

class A
{
public:
void test(string &a);
Function takes argument by refernce. Meaning that it can take only

l-values. Now, I had a lot of time understanding what l-values are, so
I'll try to makes things a bit nicer for you:

l-values are:
=============
1. *things* or entities that can appear on the LHS of an assignment
operation, or simply, the = sign.

2. Has a name and can be referred to by using that name.

Defn. 2 seems to be more appropriate to me.

r-values are:
=============
1. Things that can appear on the RHS of an assignment. Here l-values also
qualify, so we can assume this point is un-satisfactory.

2. Things that do not have a name, but do exist, so they can not be
modified directly.

Quote:
};

class B
{
public:
string test2();
};


int main()
{
A a;
B b;

a.test(b.test2());
Here, the return from test2 is an r-value, meaning that it does not have a

name, since it is a temporary.
Hence, it can not be bound to a reference.

Quote:

return 0;
}

Proposed solution:
==================

Make test take arguments by reference to constant or by value.


Regards,
-Dhruv.


ps. Yes, I have been reading quite a few DR's off late ;-)


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

Back to top
John Potter
Guest





PostPosted: Sun Dec 28, 2003 10:07 am    Post subject: Re: Template argument passed by reference Reply with quote

On 27 Dec 2003 10:48:20 -0500, Francis Glassborow
<francis (AT) robinton (DOT) demon.co.uk> wrote:

Quote:
bash-2.05b$ gcc test.cpp
test.cpp: Dans function ‹ int main() ›:
test.cpp:22: error: no matching function for call to `A::test(std::string)'
test.cpp:7: error: candidates are: void A::test(std::string&)

Not a particularly helpful error message.

What more could you ask for? It says no match for call by value, but
found call by reference. It says what every reply has said.

John

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

Back to top
Francis Glassborow
Guest





PostPosted: Sun Dec 28, 2003 4:03 pm    Post subject: Re: Template argument passed by reference Reply with quote

In message <MPG.1a5805e88d11cb2b989689 (AT) news (DOT) free.fr>, Olivier Brunet
<news.20.obrunet (AT) spamgourmet (DOT) com> writes
Quote:
void func()
{

A a;
a.test(ostream("tmpfile.tmp"));
}

Which is very convenient, but can't be written using 'const' as the
function writes to the stream.

and the solution is to eliminate the temporary:

A a;
{ // create a local scope
ostream b("tmpfile.tmp");
a.test(b);
}

A little more tedious but not much.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
or http://www.robinton.demon.co.uk
Happy Xmas, Hanukkah, Yuletide, Winter/Summer Solstice to all.


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

Back to top
Francis Glassborow
Guest





PostPosted: Sun Dec 28, 2003 4:03 pm    Post subject: Re: Template argument passed by reference Reply with quote

In message <9daruv8q89bnv59rj51njadbpm49tf90h5 (AT) 4ax (DOT) com>, John Potter
<jpotter (AT) falcon (DOT) lhup.edu> writes
Quote:
On 27 Dec 2003 10:48:20 -0500, Francis Glassborow
[email]francis (AT) robinton (DOT) demon.co.uk[/email]> wrote:

bash-2.05b$ gcc test.cpp
test.cpp: Dans function ‹ int main() ›:
test.cpp:22: error: no matching function for call to `A::test(std::string)'
test.cpp:7: error: candidates are: void A::test(std::string&)

Not a particularly helpful error message.

What more could you ask for? It says no match for call by value, but
found call by reference. It says what every reply has said.

Cannot bind rvalue to non-constant reference.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
or http://www.robinton.demon.co.uk
Happy Xmas, Hanukkah, Yuletide, Winter/Summer Solstice to all.


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

Back to top
John Potter
Guest





PostPosted: Sun Dec 28, 2003 5:16 pm    Post subject: Re: Template argument passed by reference Reply with quote

On 28 Dec 2003 05:06:45 -0500, "Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote:

Quote:
Function takes argument by refernce. Meaning that it can take only
l-values. Now, I had a lot of time understanding what l-values are, so
I'll try to makes things a bit nicer for you:

l-values are:
=============
1. *things* or entities that can appear on the LHS of an assignment
operation, or simply, the = sign.

Bad start. For UDT, operator= is a member function which may be
invoked on rvalues.

string() = "Hello";

Rvalue on lhs.

int const& r(42);

R is an lvalue which may not be used on the lhs of an assignment.

Quote:
2. Has a name and can be referred to by using that name.

Nope. The above discarded expression is an lvalue of type string&
because operator= returns a reference and all references are lvalues.
Lvalues do not all have names.

Quote:
r-values are:
=============
1. Things that can appear on the RHS of an assignment. Here l-values also
qualify, so we can assume this point is un-satisfactory.

Not much use, as you say.

Quote:
2. Things that do not have a name, but do exist, so they can not be
modified directly.

See above, there are unnamed lvalues.

Rvalue is really easy. All expressions are either lvalues or rvalues.
All expressions which are not lvalues are rvalues.

Now all you need to do is nail down lvalue. ;-)

John

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

Back to top
John Potter
Guest





PostPosted: Sun Dec 28, 2003 10:48 pm    Post subject: Re: Template argument passed by reference Reply with quote

On 28 Dec 2003 05:10:01 -0500, Olivier Brunet
<news.20.obrunet (AT) spamgourmet (DOT) com> wrote:

Quote:
Is there another way to rewrite it in a more compliant manner without
using a named variable ?

class A
{
public:
void test(std::ostream &a);
};

void func()
{

A a;
a.test(ostream("tmpfile.tmp"));
}

Which is very convenient, but can't be written using 'const' as the
function writes to the stream.

Just look for some rvalue to lvalue member function. In this case,
flush will serve the purpose. I don't think you will find that
flushing a newly created stream will be a performance problem.

a.test(ostream("tmpfile.tmp").flush());

John

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

Back to top
Peter Koch Larsen
Guest





PostPosted: Mon Dec 29, 2003 11:06 am    Post subject: Re: Template argument passed by reference Reply with quote


"John Potter" <jpotter (AT) falcon (DOT) lhup.edu> skrev i en meddelelse
news:uiduuv8tqqijudtjpidak9qil87tcfmdeh (AT) 4ax (DOT) com...
Quote:
On 28 Dec 2003 05:10:01 -0500, Olivier Brunet
[email]news.20.obrunet (AT) spamgourmet (DOT) com[/email]> wrote:

Is there another way to rewrite it in a more compliant manner without
using a named variable ?

class A
{
public:
void test(std::ostream &a);
};

void func()
{

A a;
a.test(ostream("tmpfile.tmp"));
}

Which is very convenient, but can't be written using 'const' as the
function writes to the stream.

Just look for some rvalue to lvalue member function. In this case,
flush will serve the purpose. I don't think you will find that
flushing a newly created stream will be a performance problem.

a.test(ostream("tmpfile.tmp").flush());

John

While this will work, it also obfuscates the code. More efficient and far
easier to understand would be to use Francis Glassborows solution:

{
ostream os("tmpfile.tmp");
a.test(os);
}

which you could place on a single line if four lines are considered to
verbose.

Kind regards
Peter



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

Back to top
Rani Sharoni
Guest





PostPosted: Tue Dec 30, 2003 5:10 am    Post subject: Re: Template argument passed by reference Reply with quote

John Potter <jpotter (AT) falcon (DOT) lhup.edu> wrote in message
Quote:
Nope. The above discarded expression is an lvalue of type string&
because operator= returns a reference and all references are lvalues.
Lvalues do not all have names.

Unnamed lvalues:
int A[10] = { 0 };
A[0]; // lvalue of type int[10]
int *p = A;
*p; // lvalue of type int
"hello"; // lvalue of type char[6]
"hello"[0]; lvalue of type char const

There are many less explicit examples (e.g. elements in container).

Named rvalues is narrower case:
enum { NAMED_ONE = 1 } enum_type;
NAMED_ONE; // rvalue of type
1; // rvalue of type int
'A'; // rvalue of type char

Named rvalues are actually names of constants.

Quote:
Rvalue is really easy. All expressions are either lvalues or rvalues.
All expressions which are not lvalues are rvalues.

Now all you need to do is nail down lvalue. Wink

Lvalue characteristic: Expression e of type T is an lvalue iff
reinterpret_cast<T&>(e) is well formed.
This characteristic merely says that lvalue expressions are
addressable using the built-in address operator.

I (and overloading) try to think about expressions as functions and in
this sense the lvalue expression function return type is reference.
For example:
*p; // int& operator*(int*) -> lvalue of type int
int a = 0;
a; // identity lvalue expression with return type int&
a + 1; // int operator+(int, int) -> rvalue of type int

Rani

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

Back to top
Dhruv
Guest





PostPosted: Tue Dec 30, 2003 5:17 am    Post subject: Re: Template argument passed by reference Reply with quote

On Sun, 28 Dec 2003 12:16:35 -0500, John Potter wrote:

Quote:
On 28 Dec 2003 05:06:45 -0500, "Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote:

Function takes argument by refernce. Meaning that it can take only
l-values. Now, I had a lot of time understanding what l-values are, so
I'll try to makes things a bit nicer for you:

l-values are:
=============
1. *things* or entities that can appear on the LHS of an assignment
operation, or simply, the = sign.

Bad start. For UDT, operator= is a member function which may be
invoked on rvalues.

string() = "Hello";

Rvalue on lhs.

int const& r(42);

R is an lvalue which may not be used on the lhs of an assignment.

Yes.

Quote:
2. Has a name and can be referred to by using that name.

Nope. The above discarded expression is an lvalue of type string&
because operator= returns a reference and all references are lvalues.
Lvalues do not all have names.

r-values are:
=============
1. Things that can appear on the RHS of an assignment. Here l-values also
qualify, so we can assume this point is un-satisfactory.

Not much use, as you say.

2. Things that do not have a name, but do exist, so they can not be
modified directly.

See above, there are unnamed lvalues.

Rvalue is really easy. All expressions are either lvalues or rvalues.
All expressions which are not lvalues are rvalues.

Now all you need to do is nail down lvalue. Wink

That's my point. I haven't found a sort of *formula* that when applied can
tell whether this is an l-value or an r-value. Because of so many
complications in C++, this is I guess is very hard to define in a single
sentence or even a couple of sentences. I guess that's why I haven't found
a single source that can tell me accurately how to determine whether a
given thing is an l-value or an r-value.

What I tried to present was a very simple easy to understand definition
which may not be applicable in all cases, but can be applied fairly
accurately to most commoly seen and used cases. Then of course if you do
run into trouble, the standard is always there, and you are bound to find
some ambiguity there too!


Regards,
-Dhruv.




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

Back to top
Ron Natalie
Guest





PostPosted: Tue Dec 30, 2003 8:31 pm    Post subject: Re: Template argument passed by reference Reply with quote


"Rani Sharoni" <rani_sharoni (AT) hotmail (DOT) com> wrote

Quote:
John Potter <jpotter (AT) falcon (DOT) lhup.edu> wrote in message
Nope. The above discarded expression is an lvalue of type string&
because operator= returns a reference and all references are lvalues.
Lvalues do not all have names.

Unnamed lvalues:
int A[10] = { 0 };
A[0]; // lvalue of type int[10]

Nope, type int. Just A is of type int[10]

Quote:
int *p = A;
*p; // lvalue of type int
"hello"; // lvalue of type char[6]
const char[6];


Quote:
Lvalue characteristic: Expression e of type T is an lvalue iff
reinterpret_cast<T&>(e) is well formed.

That's a lousy definition.

Quote:
This characteristic merely says that lvalue expressions are
addressable using the built-in address operator.

Which is not a definition either.

Here is the text from a previous discussion on the topic

To invert that the way you want it:

lvalue: any expression that is not an rvalue.

The rest of 3.10 goes on to explain what expressions are rvalues.
- Returns from functions that do not return a reference
- temporaries from cast to non-reference types
- the result of certain builtin operators
- things that are not objects.




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

Back to top
Ron Natalie
Guest





PostPosted: Tue Dec 30, 2003 8:32 pm    Post subject: Re: Template argument passed by reference Reply with quote


"Dhruv" <dhruvbird (AT) gmx (DOT) net> wrote


Quote:

R is an lvalue which may not be used on the lhs of an assignment.

Yes.

Yes it is extrememly unfortunate that C++ defines these concepts using the term
l-value and r-value. In fact, in C++, they have little to do with left and right sides
of the assignment operator. They might have called them s-values and e-values
to stave off some of the confusion.



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

Back to top
Rani Sharoni
Guest





PostPosted: Wed Dec 31, 2003 1:15 pm    Post subject: Re: Template argument passed by reference Reply with quote

Ron Natalie wrote:
Quote:
"Rani Sharoni" <rani_sharoni (AT) hotmail (DOT) com> wrote in message
news:df893da6.0312290649.68c9bd62 (AT) posting (DOT) google.com...
John Potter <jpotter (AT) falcon (DOT) lhup.edu> wrote in message
Nope. The above discarded expression is an lvalue of type string&
because operator= returns a reference and all references are
lvalues.
Lvalues do not all have names.

Unnamed lvalues:
int A[10] = { 0 };
A[0]; // lvalue of type int[10]

Nope, type int. Just A is of type int[10]

I had typo - I meant that A is an lvalue of type int[10] as you noted.

Quote:
int *p = A;
*p; // lvalue of type int
"hello"; // lvalue of type char[6]
const char[6];

This type is tricky but I agree with your correction. It's *special* lvalue
of type const char[6].

Quote:
Lvalue characteristic: Expression e of type T is an lvalue iff
reinterpret_cast<T&>(e) is well formed.

That's a lousy definition.

But extremely accurate characteristic.


Quote:
This characteristic merely says that lvalue expressions are
addressable using the built-in address operator.

Which is not a definition either.

It's a characteristic.

Quote:
Here is the text from a previous discussion on the topic

To invert that the way you want it:

I prefer simple characteristic.

Quote:
lvalue: any expression that is not an rvalue.

The rest of 3.10 goes on to explain what expressions are rvalues.
- Returns from functions that do not return a reference
- temporaries from cast to non-reference types
- the result of certain builtin operators
- things that are not objects.

There are lvalue expressions of functions type and these types are not
objects types. 3.10/2 is clear about that.

void f();

f; // lvalue expression of type void()



As I also mentioned, lvalue expressions are like calling functions that
returns reference.



Thanks,

Rani





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

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.