 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
pongba@gmail.com Guest
|
Posted: Mon Oct 24, 2005 4:38 pm Post subject: suggest loosen the type deduction rule |
|
|
the motivation example is:
#include<string>
#include<iostream>
using namespace std;
class S
{
public:
operator string(){return " ";}
};
int main()
{
std::cout<
return 0;
}
true,there exists a quite simple and obvious alternative, that is,
change 'S()' to 'string(S())' or '(string)S()'.
also,this has no essential effect on code correctness, semantic
,whatever. But can anyone promise that nothing harmful would be caused
by this inconvenience?
For example, assume someone who write down such code and surely expects
it works,but it doesn't,and the error message is quite puzzling,which
basically says that "no viable function(s) found,the candidates are
....",but the candidate functions it lists out doesn't contain the one
that takes a right-hand operator of type std::basic_string<...> const&,
because it has been kicked out of the candidate set because of type
deduction failure.
And there's a little consideration as to code elegance ...
On the other hand, loosen the type deduction rule a little bit seems
not hurting the type system or language complexity.
14.8.2.1/3 lists out the exceptions. We can add another one(or modify
the last bullet):
if P is a class and P has the form template-id, normal conversion that
is allowed in any other cases are allowed here, if there exists more
than one conversion paths(possibility) that lead to different deduced
A,type deduction fails[example:
template<typename T>
struct X
{
X(int);
};
template<typename T>
void f(X<T>);
int main()
{
f(0); // 0 can be converted to X<T> whatever T is,in other
words,there exists infinitude path, so type deduction fails of cause.
}
My question is, why not allow this, if its because of language
complexity related consideration, please anyone tell me the rationale,
thanks in advance;-)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Greg Herlihy Guest
|
Posted: Wed Oct 26, 2005 1:15 pm Post subject: Re: suggest loosen the type deduction rule |
|
|
[email]pongba (AT) gmail (DOT) com[/email] wrote:
| Quote: | the motivation example is:
#include<string
#include
using namespace std;
class S
{
public:
operator string(){return " ";}
};
int main()
{
std::cout<
return 0;
}
true,there exists a quite simple and obvious alternative, that is,
change 'S()' to 'string(S())' or '(string)S()'.
|
It is not at all obvious that simply because an object has a conversion
function, that that conversion function is the one to invoke to output
an object of that class to a stream. It seems to me that if a class can
be streamed at all, that its output would be more elaborate than a
single std::string. But only the programmer knows for sure how
std::cout << S() should be handled. So rather than have the compiler
guess, the program should specify the intended behavior and do so - not
by an explicit type conversion as the example shows - but by an
explicit type overload:
ostream& operator<<(ostream& stream, const S& s)
{
stream << (string) s; // or whatever
...
return stream;
}
Once this routine has been written, the question of implicit versus
explicit type conversions becomes moot.
| Quote: | also,this has no essential effect on code correctness, semantic
,whatever. But can anyone promise that nothing harmful would be caused
by this inconvenience?
|
If the type conversion does harm, this proposal will do nothing to
alleviate that harm. The type conversion would still take place, only
its invocation could be implicit in addition to the explicit conversion
supported today. And in fact, many would find the implicit type
conversion more harmful, since its invocation is far less apparent in
the source code.
| Quote: | For example, assume someone who write down such code and surely expects
it works,but it doesn't,and the error message is quite puzzling,which
basically says that "no viable function(s) found,the candidates are
...",but the candidate functions it lists out doesn't contain the one
that takes a right-hand operator of type std::basic_string<...> const&,
because it has been kicked out of the candidate set because of type
deduction failure.
And there's a little consideration as to code elegance ...
On the other hand, loosen the type deduction rule a little bit seems
not hurting the type system or language complexity.
14.8.2.1/3 lists out the exceptions. We can add another one(or modify
the last bullet):
if P is a class and P has the form template-id, normal conversion that
is allowed in any other cases are allowed here, if there exists more
than one conversion paths(possibility) that lead to different deduced
A,type deduction fails[example:
template<typename T
struct X
{
X(int);
};
template
void f(X
int main()
{
f(0); // 0 can be converted to X<T> whatever T is,in other
words,there exists infinitude path, so type deduction fails of cause.
}
My question is, why not allow this, if its because of language
complexity related consideration, please anyone tell me the rationale,
thanks in advance;-)
|
You may wish to take up this suggestion with the readers of
comp.std.c++. But given that implicit conversions are not well regarded
in general, I would not expect that a proposal to extend their scope of
operation would be enthusiastically embraced. But there is no harm in
asking.
The core problem with implicit conversions is that it lets the compiler
write code. Unfortunately, the compiler isn't very good at writing
software, or intuiting what the programmer intends to happen in a
particular situation; therefore oftentimes the code that the compiler
supplies (in the form of implicit convesions) is neither helpful nor
even expected.
Greg
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
mlybbert Guest
|
Posted: Thu Oct 27, 2005 10:32 am Post subject: Re: suggest loosen the type deduction rule |
|
|
| Quote: | class S
{
public:
operator string(){return " ";}
};
int main()
{
std::cout<
return 0;
}
|
I'm not sure you're doing what you think you are. std::cout << S() is
calling the class's constructor, which doesn't return a string (it
returns an object of type "S"). I don't know of any operator string(),
so I assumed you were thinking
std::string operator()() { return std::string(" ");}
Which can be used after you've constructed an object:
int main()
{ S my_obj();
std::cout << my_obj();
}
But I'm not sure. If you were trying to write a conversion to string,
that may explain why a cast to string would get rid of your error.
OTOH, the Correct Way was already suggested, define an operator<< that
returns a std::ostream.
[ 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: Thu Oct 27, 2005 4:41 pm Post subject: Re: suggest loosen the type deduction rule |
|
|
In article <1130371788.315662.246730 (AT) g14g2000cwa (DOT) googlegroups.com>,
mlybbert <mlybbert (AT) users (DOT) sourceforge.net> writes
| Quote: | class S
{
public:
operator string(){return " ";}
};
int main()
{
std::cout<
return 0;
}
I'm not sure you're doing what you think you are. std::cout << S() is
calling the class's constructor, which doesn't return a string (it
returns an object of type "S"). I don't know of any operator string(),
so I assumed you were thinking
|
Then it is time to do some learning. operator string() is the syntax C++
uses to declare a member function that provides a type conversion from
the type being defined to the type specified. So in this case it
provides a conversion from an instance of S to a string value.
The problem, I think, is that the compiler does not know of a type
called string (the writer probably meant std::string.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Allan W Guest
|
Posted: Fri Oct 28, 2005 9:06 am Post subject: Re: suggest loosen the type deduction rule |
|
|
mlybbert wrote:
| Quote: | int main()
{ S my_obj();
std::cout << my_obj();
}
|
Do you realize that my_obj is a function, taking no parameters and
returning an S object? And the next line calls that function?
If you realized that, it wasn't obvious... you show no definition
of my_obj.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze Guest
|
Posted: Sat Oct 29, 2005 1:11 pm Post subject: Re: suggest loosen the type deduction rule |
|
|
Francis Glassborow wrote:
| Quote: | In article <1130371788.315662.246730 (AT) g14g2000cwa (DOT) googlegroups.com>,
mlybbert <mlybbert (AT) users (DOT) sourceforge.net> writes
class S
{
public:
operator string(){return " ";}
};
int main()
{
std::cout<
return 0;
}
I'm not sure you're doing what you think you are. std::cout
S() is calling the class's constructor, which doesn't
return a string (it returns an object of type "S"). I don't
know of any operator string(), so I assumed you were thinking
Then it is time to do some learning. operator string() is the
syntax C++ uses to declare a member function that provides a
type conversion from the type being defined to the type
specified. So in this case it provides a conversion from an
instance of S to a string value.
The problem, I think, is that the compiler does not know of a
type called string (the writer probably meant std::string.
|
The original code had a "using namespace std;" immediately after
the includes. It's quite clear which string is meant.
The original poster pointed out the actual problem quite exactly
(and showed a very good knowledge of C++ in doing so -- it's far
from evident, and had he not pointed it out, I'm not sure I
would have spotted it). The std::operator<< function which is
needed is a template. And the type conversion in question
doesn't occur during type deduction, so the appropriate
operator<< function never gets instantiated, never makes it into
the overload set, and so, of course, can't be chosen by overload
resolution.
Note that this doesn't work with an operator char const* either;
the problem is the same. And that is does work with operator
char const* in the classical streams. This is something that
the committee broke when they made iostream a template.
A sort of a weak justification would be that it is bad code
anyway, that you shouldn't use an implicit conversion for this
sort of thing.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
syntetic@mail.ru Guest
|
Posted: Sat Oct 29, 2005 1:11 pm Post subject: Re: suggest loosen the type deduction rule |
|
|
[email]pongba (AT) gmail (DOT) com[/email] wrote:
| Quote: | the motivation example is:
#include<string
#include
using namespace std;
class S
{
public:
operator string(){return " ";}
};
int main()
{
std::cout<
return 0;
}
true,there exists a quite simple and obvious alternative, that is,
change 'S()' to 'string(S())' or '(string)S()'.
also,this has no essential effect on code correctness, semantic
,whatever. But can anyone promise that nothing harmful would be caused
by this inconvenience?
For example, assume someone who write down such code and surely expects
it works,but it doesn't,and the error message is quite puzzling,which
basically says that "no viable function(s) found,the candidates are
....",but the candidate functions it lists out doesn't contain the one
that takes a right-hand operator of type std::basic_string<...> const&,
because it has been kicked out of the candidate set because of type
deduction failure.
And there's a little consideration as to code elegance ...
On the other hand, loosen the type deduction rule a little bit seems
not hurting the type system or language complexity.
14.8.2.1/3 lists out the exceptions. We can add another one(or modify
the last bullet):
if P is a class and P has the form template-id, normal conversion that
is allowed in any other cases are allowed here, if there exists more
than one conversion paths(possibility) that lead to different deduced
A,type deduction fails[example:
template<typename T
struct X
{
X(int);
};
template
void f(X
int main()
{
f(0); // 0 can be converted to X<T> whatever T is,in other
words,there exists infinitude path, so type deduction fails of cause.
}
My question is, why not allow this, if its because of language
complexity related consideration, please anyone tell me the rationale,
thanks in advance;-)
|
If you change in "motivation example" operator string() to operator
int() you will achieve desired behavior. It's the matter of STL
implementation. If you take a look at operator << for the string you
will see:
template
class _Traits,
class _Alloc> inline
basic_ostream<_Elem, _Traits>& __cdecl operator<<(
basic_ostream<_Elem, _Traits>& _Ostr,
const basic_string<_Elem, _Traits, _Alloc>& _Str)
{
....
Thus compiler needs to make two translations: one - to construct
std::string from class S and second - to instantiate operator << for
the string. It's forbidden by the standard. You can write your own
operator << for the string, just delegating call to template:
#include
#include <iostream>
class A {
public:
operator std::string () { return "0123456789"; }
};
std::ostream& operator << ( std::ostream& stream, const std::string&
string ) {
return std::operator << ( stream, string );
}
int main() {
std::cout << A() << std::endl;
return 0;
}
Alexander Kozlov.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
mlybbert Guest
|
Posted: Sat Oct 29, 2005 7:42 pm Post subject: Re: suggest loosen the type deduction rule |
|
|
Sorry, Allan, maybe my original code examples did not make it clear
they were meant to be used (1) together, and (2) in conjunction with
the original post:
#include <string>
#include <iostream>
class S
{
public:
std::string operator()() { return std::string(" ");}
};
int main()
{ S my_obj();
std::cout << my_obj();
return 0;
}
In which case, my_obj is an instance of class S, and all instances of
class S have an operator() that takes no parameters, and returns a
std::string consisting of one space. The technique is called a functor
or function-like object.
But, thanks to Francis Glassborow, I learned the original post was
supposed to do what the original poster expected it to.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
James Kanze Guest
|
Posted: Sun Oct 30, 2005 3:31 am Post subject: Re: suggest loosen the type deduction rule |
|
|
mlybbert wrote:
| Quote: | Sorry, Allan, maybe my original code examples did not make it
clear they were meant to be used (1) together, and (2) in
conjunction with the original post:
|
I think Allan knew that.
| Quote: | #include <string
#include
class S
{
public:
std::string operator()() { return std::string(" ");}
};
int main()
{ S my_obj();
std::cout << my_obj();
return 0;
}
In which case, my_obj is an instance of class S,
|
No it's not. That's Allan's point. As written, my_obj is an
external function taking no parameters, and returning an S. In
the following line, you call the function.
I don't know what compiler you tried this with. Logically, you
should get exactly the same error as the original poster, so the
code won't compile. If you insert a cast manually:
std::cout << static_cast< std::string >( my_obj() ) ;
it of course compiles, but you should get an error from the
linker about a missing definition for my_obj.
If you're seeing anything else, you're compiler isn't conform.
| Quote: | and all instances of class S have an operator() that takes no
parameters, and returns a std::string consisting of one space.
The technique is called a functor or function-like object.
But, thanks to Francis Glassborow, I learned the original post
was supposed to do what the original poster expected it to.
|
And thanks to Allan's posting, you've learned about C++'s most
aggravating parse problem:-).
--
James Kanze mailto: [email]james.kanze (AT) free (DOT) fr[/email]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze Guest
|
Posted: Tue Nov 01, 2005 9:44 am Post subject: Re: suggest loosen the type deduction rule |
|
|
[email]syntetic (AT) mail (DOT) ru[/email] wrote:
| Quote: | pongba (AT) gmail (DOT) com wrote:
the motivation example is:
#include<string
#include
using namespace std;
class S
{
public:
operator string(){return " ";}
};
int main()
{
std::cout<
return 0;
}
true,there exists a quite simple and obvious alternative,
that is, change 'S()' to 'string(S())' or '(string)S()'.
also,this has no essential effect on code correctness,
semantic, whatever. But can anyone promise that nothing
harmful would be caused by this inconvenience?
For example, assume someone who write down such code and
surely expects it works,but it doesn't,and the error message
is quite puzzling,which basically says that "no viable
function(s) found,the candidates are ....",but the candidate
functions it lists out doesn't contain the one that takes a
right-hand operator of type std::basic_string<...> const&,
because it has been kicked out of the candidate set because
of type deduction failure.
And there's a little consideration as to code elegance ...
On the other hand, loosen the type deduction rule a little
bit seems not hurting the type system or language
complexity.
14.8.2.1/3 lists out the exceptions. We can add another
one(or modify the last bullet):
if P is a class and P has the form template-id, normal
conversion that is allowed in any other cases are allowed
here, if there exists more than one conversion
paths(possibility) that lead to different deduced A,type
deduction fails[example:
template<typename T
struct X
{
X(int);
};
template
void f(X
int main()
{
f(0); // 0 can be converted to X<T> whatever T is,in other
words,there exists infinitude path, so type deduction fails of cause.
}
My question is, why not allow this, if its because of
language complexity related consideration, please anyone
tell me the rationale, thanks in advance;-)
If you change in "motivation example" operator string() to
operator int() you will achieve desired behavior.
|
That's true, but not at all for the reasons you say. <
member function, not a global function. As such, it's
declaration is instantiated when the class is instantiated, so
the operator is available for overload resolution.
| Quote: | It's the matter of STL implementation. If you take a look at
operator << for the string you will see:
template
class _Traits,
class _Alloc> inline
basic_ostream<_Elem, _Traits>& __cdecl operator<<(
basic_ostream<_Elem, _Traits>& _Ostr,
const basic_string<_Elem, _Traits, _Alloc>& _Str)
{
...
Thus compiler needs to make two translations:
|
What exactly do you mean by translations, here. There is
exactly one conversion, in both his case and yours.
| Quote: | one - to construct std::string from class S and second - to
instantiate operator << for the string.
|
It's not a question of two anything. String or int, there is
one user defined conversion operator, which is allowed in
function overloading. The problem is that user defined
conversion operators are not taken into account during template
type deduction; since op<< for string is a global template
function, its declaration needs to be instantiated for it to be
considered by overload resolution. The second parameter of the
op<< string is a type which depends on the the template, so it
is taken into account for type deduction. And since type
deduction doesn't take any user defined conversions into
account, the template doesn't get instantiated, and the function
is not considered during overload resolution.
| Quote: | It's forbidden by the standard. You can write your own
operator << for the string,
|
That sounds like a recepe for trouble. Anytime type deduction
does instantiate the standard function, you end up with an
ambiguity.
| Quote: | just delegating call to template:
#include
#include
class A {
public:
operator std::string () { return "0123456789"; }
};
std::ostream& operator << ( std::ostream& stream, const std::string&
string ) {
return std::operator << ( stream, string );
}
int main() {
std::cout << A() << std::endl;
return 0;
}
|
Yes, but now something simple like:
std::string s( "abcd" ) ;
std::cout << s ;
fails.
In this case, the problem is depending on implicite conversion
functions. A better solution would have involved writing an
operator<< for the class in question, so no conversion would be
necessary.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
mlybbert Guest
|
Posted: Wed Nov 02, 2005 11:37 am Post subject: Re: suggest loosen the type deduction rule |
|
|
/* As written, my_obj is an external function taking no parameters, and
returning an S. In the following line, you call the function.
*/
Alright, how would I create an object of type S, call it my_obj, and
place it on the stack instead of the heap? Remember, the constructor
for S doesn't take any parameters.
Yes, I could have written "S* my_obj_on_the_heap = new S;" but I want
it on the stack, so I don't have to delete anything manually.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
mlybbert Guest
|
Posted: Wed Nov 02, 2005 11:38 am Post subject: Re: suggest loosen the type deduction rule |
|
|
To be honest, James, I have not tried compiling my example. I was
simply following the pattern of a funtion-like object. There is an
example at http://www.research.att.com/~bs/bs_faq2.html#function-object
You'll also note that the same page has an example of a user defined
conversion in the mode of "operator string," so I whould have known
what the original post was about.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze Guest
|
Posted: Thu Nov 03, 2005 1:06 pm Post subject: Re: suggest loosen the type deduction rule |
|
|
mlybbert wrote:
| Quote: | /* As written, my_obj is an external function taking no
parameters, and returning an S. In the following line, you
call the function. */
Alright, how would I create an object of type S, call it
my_obj, and place it on the stack instead of the heap?
Remember, the constructor for S doesn't take any parameters.
|
S my_obj ;
This is pretty much basic C++. Adding the parentheses is a
classical beginner's mistake, and is generally covered fairly
early in any C++ course, because the fact that you cannot add
them (for historical reasons) IS somewhat counter-intuitive.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ 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
|
|