T t(a) not equivalent to T t = a

O

Old Wolf

I often see it written here that the declaration
T t = a;
(where 'a' is not of type T) calls the copy-constructor and
is exactly equivalent to
T t(( T(a) ));

However the following code gives me a compiler error:

#include <string>

struct M
{
M(std::string const &s);
};

int main()
{
M a ("Hello");
M b = M("Hello");
M c ( M("Hello") );
M d = "Hello";
return 0;
}

m.cc:13: error: conversion from `const char[6]' to non-scalar type `M'
requested

The error is one the "M d" line, and the other lines compiled
correctly. What's going on?
 
B

benben

Old Wolf said:
I often see it written here that the declaration
T t = a;
(where 'a' is not of type T) calls the copy-constructor and
is exactly equivalent to
T t(( T(a) ));

However the following code gives me a compiler error:

#include <string>

struct M
{
M(std::string const &s);
};

int main()
{
M a ("Hello");
M b = M("Hello");
M c ( M("Hello") );
M d = "Hello";
return 0;
}

m.cc:13: error: conversion from `const char[6]' to non-scalar type `M'
requested

The error is one the "M d" line, and the other lines compiled
correctly. What's going on?

M d = std::string("Hello"); // expecting std::string

Implicity convertion to std::string from char* is not allowed, I guess...

Ben
 
M

Me

Old said:
I often see it written here that the declaration
T t = a;
(where 'a' is not of type T) calls the copy-constructor and
is exactly equivalent to
T t(( T(a) ));

However the following code gives me a compiler error:

#include <string>

struct M
{
M(std::string const &s);
};

int main()
{
M a ("Hello");
M b = M("Hello");
M c ( M("Hello") );
M d = "Hello";
return 0;
}

m.cc:13: error: conversion from `const char[6]' to non-scalar type `M'
requested

The error is one the "M d" line, and the other lines compiled
correctly. What's going on?

Totally simplified answer: the standard limits up to 2 implicit
conversions to occur. Variable d looks like const char[6] -> const char
* (this one is a freebie so it doesn't really count) -> std::string ->
M.
 
G

Greg

Old said:
I often see it written here that the declaration
T t = a;
(where 'a' is not of type T) calls the copy-constructor and
is exactly equivalent to
T t(( T(a) ));

However the following code gives me a compiler error:

#include <string>

struct M
{
M(std::string const &s);
};

int main()
{
M a ("Hello");
M b = M("Hello");
M c ( M("Hello") );
M d = "Hello";
return 0;
}

m.cc:13: error: conversion from `const char[6]' to non-scalar type `M'
requested

The error is one the "M d" line, and the other lines compiled
correctly. What's going on?

The problem in line 13 (the last line before the return statement) is
that it requires two user-defined implicit conversions:

const char[6] -> std::string -> M

in order to complete the operation. The C Standard limits user-defined
implicit conversions of a single value to no more than one in any
single expression.

Greg
 
A

Aries Sun

The error seems very simple, you didn't implement the constructor, but
you have define the constructor explicitly.

Try the following:

struct M
{
M(std::string const &s){};
};

Aries Sun
 
M

msalters

Aries Sun schreef:
The error seems very simple, you didn't implement the constructor, but
you have define the constructor explicitly.

True, but that doesn't give you a compiler error. Missing definitions
cause linker errors. The OP might link to M.cpp which defines the M
ctor.
The other explanations are correct, though: there is no conversion
from char const* to M.

HTH,
Michiel Salters
 
O

Old Wolf

Me said:
Old said:
I often see it written here that the declaration
T t = a;
(where 'a' is not of type T) calls the copy-constructor and
is exactly equivalent to
T t(( T(a) ));

However the following code gives me a compiler error:

#include <string>

struct M
{
M(std::string const &s);
};

int main()
{
M a ("Hello");
M b = M("Hello");
M c ( M("Hello") );
M d = "Hello";
return 0;
}

m.cc:13: error: conversion from `const char[6]' to non-scalar type `M'
requested

The error is one the "M d" line, and the other lines compiled
correctly. What's going on?

Totally simplified answer: the standard limits up to 2 implicit
conversions to occur. Variable d looks like const char[6] -> const char
* (this one is a freebie so it doesn't really count) -> std::string ->
M.

So why does the "M a" line compile? That has two conversions:
const char[6] -> std::string -> M.

I guess you saying that the ( ) syntax counts as an explicit
conversion but the = syntax does not, even though they are
both initialization?
 
M

Me

Old said:
struct M
{
M(std::string const &s);
};
Totally simplified answer: the standard limits up to 2 implicit
conversions to occur. Variable d looks like const char[6] -> const char
* (this one is a freebie so it doesn't really count) -> std::string ->
M.

So why does the "M a" line compile? That has two conversions:
const char[6] -> std::string -> M.

What I meant by the above deals with where the compiler generates its
own temporaries to do the conversion as opposed to the programmer
explicitly creating an unnamed object along the way.
I guess you saying that the ( ) syntax counts as an explicit
conversion but the = syntax does not, even though they are
both initialization?

Greg's answer in this thread was better than mine since he had it in
terms of user defined conversions and mine was just implicit
conversions while not counting the freebies that occur. But if you're
still confused, here is how the compiler might expand these to (I'm
going to use trailing underscores to note the temporaries the compiler
generates):

M a("Hello");
// becomes:
std::string temp_("Hello");
M a(temp_);

M b = M("Hello");
// becomes:
std::string temp_("Hello");
M temp(temp_);
M b(temp);

M c ( M("Hello") );
// becomes:
std::string temp_("Hello");
M temp(temp_);
M c(temp);

M d = "Hello";
// becomes:
std::string temp_("Hello");
M temp__(temp_);
M d(temp__);

M e = std::string("Hello");
// becomes:
std::string temp("Hello");
M temp_(temp);
M e(temp_);

I hope you can see why d doesn't work but the others do.
 

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
474,434
Messages
2,571,691
Members
48,796
Latest member
Greg L.

Latest Threads

Top