 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Thomas Mang Guest
|
Posted: Sat Dec 27, 2003 3:36 pm Post subject: Re: Template argument passed by reference |
|
|
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
|
Posted: Sat Dec 27, 2003 3:38 pm Post subject: Re: Template argument passed by reference |
|
|
"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"
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
|
Posted: Sat Dec 27, 2003 3:48 pm Post subject: Re: Template argument passed by reference |
|
|
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
|
Posted: Sun Dec 28, 2003 10:06 am Post subject: Re: Template argument passed by reference |
|
|
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.
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
|
Posted: Sun Dec 28, 2003 10:07 am Post subject: Re: Template argument passed by reference |
|
|
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
|
Posted: Sun Dec 28, 2003 4:03 pm Post subject: Re: Template argument passed by reference |
|
|
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
|
Posted: Sun Dec 28, 2003 4:03 pm Post subject: Re: Template argument passed by reference |
|
|
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
|
Posted: Sun Dec 28, 2003 5:16 pm Post subject: Re: Template argument passed by reference |
|
|
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
|
Posted: Sun Dec 28, 2003 10:48 pm Post subject: Re: Template argument passed by reference |
|
|
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
|
Posted: Mon Dec 29, 2003 11:06 am Post subject: Re: Template argument passed by reference |
|
|
"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
|
Posted: Tue Dec 30, 2003 5:10 am Post subject: Re: Template argument passed by reference |
|
|
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.
|
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
|
Posted: Tue Dec 30, 2003 5:17 am Post subject: Re: Template argument passed by reference |
|
|
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.
|
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
|
Posted: Tue Dec 30, 2003 8:31 pm Post subject: Re: Template argument passed by reference |
|
|
"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
|
Posted: Tue Dec 30, 2003 8:32 pm Post subject: Re: Template argument passed by reference |
|
|
"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
|
Posted: Wed Dec 31, 2003 1:15 pm Post subject: Re: Template argument passed by reference |
|
|
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 |
|
 |
|
|
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
|
|