why assigning to mismatch type in template still works.

W

wy

Here is the code.

/* main.cpp */
#include <iostream>

template <typename T>
class test
{
public:
test(T tmp)
: t(tmp){
}

T get(){
return t;
}
void set(T tmp){
t = tmp;
}

T t;
};

int main(void){
char buf[] = "hello, world";
test<std::string> instance(buf);
std::cout << instance.get() << std::endl;
instance.set(buf + 7);
std::cout << instance.get() << std::endl;
}
/* end of main.cpp */

The output is
$ ./a.out
hello, world
world

But why will it still work when assigning a char pointer to "instance",
which accepts std::string only?
Is there any unusual relationship between std::string and char?
Or have I misunderstood the property of template?
Thanks for your help!
 
G

Gerhard Fiedler

wy said:
char* is a perfectly acceptable substitute for const char* here.
That's part of the beauty of const pointer parameters!

/Jorgen

Thank you for your help.
Yes, char* is a perfectly acceptable substitute for const char*.

/* main.cpp */
#include <iostream>

void user1(char *str){
std::cout << str << std::endl;
}

void user2(const char *str){
std::cout << str << std::endl;
}

int main(void){
const char *buf1 = "buffer 1";
char buf2[] = "buffer 2";
char *buf3 = "buffer 3";

user1(buf1);
user1(buf2);
user1(buf3);
user2(buf1);
user2(buf2);
user2(buf3);
}
/* end of main.cpp */

It will produce a warning for char *buf3 = "buffer 3", an error for
user1(buf1).
"buffer 3" can not be changed, but *buf3 can be changed.
So g++ produces a waring for safety.
Also void user1(char *str) may change the char array pointed by str, but
buf1 points to a const string.
So g++ produces an error.
Is it right?
But why these two situations are treated differently?

I think this is for historical reasons. It seems to have been common to
assign a string literal to a char* pointer (I even see this done
currently, even though I try to stomp it out before it grows :).

I'm not sure what the standard says about this, but it could be that
there's some clause that allows this specific situation -- or it's a
compiler extension. At least both compilers with which I work regularly
allow it (MSVC, GCC).

Gerhard
 
W

wy

No. There is no 'instance::set(char*)'. First off, the scope resolution
operator does not apply to variables. So, it could only be
'instance.set(something)'. And since you defined your variable
'instance' as 'test<std::string>', the 'set' member function has the
argument 'std::string', and the compiler doesn't have a single function
set of overloads, no choice but to [attempt to] convert whatever you
pass to that function to come up with a 'std::string' argument to pass
to 'set'.

When the compiler sees your call ('instance.set(buf + 7)') it does not
look at the argument, it first looks at the name "set" to see if it can
find any function to form the overloaded function set (this is a bit
simplified, of course). Then it looks at the argument if it needs to,
and in this case it doesn't need to because there is only one member
called 'set' in the 'test<std::string>' class.

V

I think it makes no difference.
First search for 'set' member functions, then search for the function
with right arguments in the recently found 'set' overloads.
Or search for the 'set' member function with right arguments all at once.
Aren't the two equivalent?
 
W

wy

On 07/14/2013 01:00 PM, wy wrote:
A related question:

std::string user(void){
char buf[1024];
return buf;
}

Is user function safe?
I mean, does user() create a new std::string initialized with the char
array pointed by buf, and return the std::string?
Because the char array may be corrupted after the heap is released.
 
I

Ike Naar

On 07/14/2013 01:00 PM, wy wrote:
A related question:

std::string user(void){
char buf[1024];
return buf;
}

Is user function safe?
I mean, does user() create a new std::string initialized with the char
array pointed by buf, and return the std::string?
Because the char array may be corrupted after the heap is released.

user() returns a newly created std::string.

However, in your example the construction of the std::string has
undefined behaviour because buf[] contains uninitialized data,
where it should contain a sero-terminated c-style string.
 
V

Victor Bazarov

No. There is no 'instance::set(char*)'. First off, the scope resolution
operator does not apply to variables. So, it could only be
'instance.set(something)'. And since you defined your variable
'instance' as 'test<std::string>', the 'set' member function has the
argument 'std::string', and the compiler doesn't have a single function
set of overloads, no choice but to [attempt to] convert whatever you
pass to that function to come up with a 'std::string' argument to pass
to 'set'.

When the compiler sees your call ('instance.set(buf + 7)') it does not
look at the argument, it first looks at the name "set" to see if it can
find any function to form the overloaded function set (this is a bit
simplified, of course). Then it looks at the argument if it needs to,
and in this case it doesn't need to because there is only one member
called 'set' in the 'test<std::string>' class.

V

I think it makes no difference.
First search for 'set' member functions, then search for the function
with right arguments in the recently found 'set' overloads.
Or search for the 'set' member function with right arguments all at once.
Aren't the two equivalent?

<shrug> Not sure how is that relevant to your original question. But
since you asked... Name lookup, overload resolution, type conversions,
etc. are all but stages in the compilation. Can you bundle them all
together and call it "compilation"? Sure. Does it help understanding
why certain things are the way they are? I don't think so. If you
don't care to understand, it's OK. If you do care, it might help to
look at the process as it is defined (and usually implemented, I
suppose), and every step is important, it has its specifics, its own
decisions that the compiler has to make, etc.

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top