conversion from '...' to non-scalar type '...' requested

T

tthunder

Hi @all,

My small example does not compile... I know, that this (as always) has
reasons, but I want to know WHY?

BTW:
I only get errors with g++ (4.x), BCB (6.0),...
VS C++ (2005) works perfectly (without warnings etc.)

class classValue
{
public:
classValue() {}
};

class classHolder
{
public: classHolder(classValue &ami) {} // <== I know, but in
this case reference MUST be non-const
};

classHolder getAHolder()
{
return classValue(); // <--- Error: conversion from
'classValue' to non-scalar type 'classHolder' requested
}


Using a little trick, everthing works well...

class classValue
{
public:
classValue() {}
classValue &self() { return *this; }
};

class classHolder
{
public: classHolder(classValue &ami) {}
};

classHolder getAHolder()
{ return classValue().self();}

But why must I use this nasty indirection?
How is this phenomenon called?
Any other suggestions?

THX,
Kirsten
 
V

Victor Bazarov

My small example does not compile... I know, that this (as always) has
reasons, but I want to know WHY?

Because it's prohibited by the Standard.
BTW:
I only get errors with g++ (4.x), BCB (6.0),...
VS C++ (2005) works perfectly (without warnings etc.)

Make sure you disable "language extensions" when compiling with VC++.
class classValue
{
public:
classValue() {}
};

class classHolder
{
public: classHolder(classValue &ami) {} // <== I know, but in
this case reference MUST be non-const
};

classHolder getAHolder()
{
return classValue(); // <--- Error: conversion from
'classValue' to non-scalar type 'classHolder' requested

That's correct. A temporary cannot be bound to a non-const reference.
}


Using a little trick, everthing works well...

class classValue
{
public:
classValue() {}
classValue &self() { return *this; }
};

class classHolder
{
public: classHolder(classValue &ami) {}
};

classHolder getAHolder()
{ return classValue().self();}

But why must I use this nasty indirection?

It's a very bad idea to actually use it.
How is this phenomenon called?

Which one? Playing dirty tricks?
Any other suggestions?

Redesign.

V
 
M

mlimber

Hi @all,

My small example does not compile... I know, that this (as always) has
reasons, but I want to know WHY?

BTW:
I only get errors with g++ (4.x), BCB (6.0),...
VS C++ (2005) works perfectly (without warnings etc.)

VS *builds* perfectly. I doubt it would actually work in practice
except by pure chance.
class classValue
{
public:
classValue() {}
};

class classHolder
{
public: classHolder(classValue &ami) {} // <== I know, but in
this case reference MUST be non-const
};

classHolder getAHolder()
{
return classValue(); // <--- Error: conversion from
'classValue' to non-scalar type 'classHolder' requested
}

You are returning type classHolder, so the return value you specify (a
*temporary* of type classValue) must be converted to a classHolder via
the constructor you supply. However, according to the C++ Standard,
non-const references cannot bind to temporaries, and that is a good
thing and for your protection.
Using a little trick, everthing works well...

class classValue
{
public:
classValue() {}
classValue &self() { return *this; }
};

class classHolder
{
public: classHolder(classValue &ami) {}
};

classHolder getAHolder()
{ return classValue().self();}

But why must I use this nasty indirection?
How is this phenomenon called?
Any other suggestions?

You are fighting against the rules of the language here, and this
trickery won't actually get you anywhere since you'll likely end up
with a dangling reference in your real code. Either don't use a
temporary or don't pass a non-const reference to
classHolder::classHolder() -- that is, either make a copy of the
classValue object or pass a const reference to it.

Cheers! --M
 
J

Jonathan Mcdougall

Hi @all,

My small example does not compile... I know, that this (as always) has
reasons, but I want to know WHY?

Because you cannot bound an rvalue to a non-const reference.
BTW:
I only get errors with g++ (4.x), BCB (6.0),...
VS C++ (2005) works perfectly (without warnings etc.)

class classValue
{
public:
classValue() {}
};

class classHolder
{
public: classHolder(classValue &ami) {} // <== I know, but in
this case reference MUST be non-const
};

classHolder getAHolder()
{
return classValue(); // <--- Error: conversion from
'classValue' to non-scalar type 'classHolder' requested

If you could do that, you'd get several more important problems:

void f(int& i)
{
i = 2;
}

int main()
{
int i = 4;
double d = 1.0;

f(i); // ok
f(d); // ok??
f(4); // ouch!

// what should this output?
std::cout << d;
}

For the second call to f(), the double gets converted to a temporary
int (an rvalue), which gets modified in f(). Do you expect 'd' to get
modified also? It won't and that's misleading, dangerous and illegal.
}

Using a little trick, everthing works well...

Yes, you may do that.
class classValue
{
public:
classValue() {}
classValue &self() { return *this; }
};

class classHolder
{
public: classHolder(classValue &ami) {}
};

classHolder getAHolder()
{ return classValue().self();}

But why must I use this nasty indirection?

Because that's how the language is defined. Note that you may also do

classholder getAHolder()
{
classValue v;
return classHolder(v);
}


Jonathan
 
T

tthunder

Yes, hate me... I believe your explanations, of course!!!!
But sometimes you NEED to be nasty.

I explain why I cannot use const...

class classHolder
{
public: classHolder(classValue &ami) {}
};

class classHolder_const : public classHolder
{
public: classHolder(const classValue &ami) {}
};

classValue aValue;
const classValue aConstValue;
classHolder aHolder1 = aValue; // <= ok
classHolder aHolder2 = aConstValue; // <= forbidden
classHolder_const aHolder3 = aValue; // <= ok
classHolder_const aHolder4 = aConstValue; // <= ok

My classHolder may NOT get any const variables.
 
V

Victor Bazarov

Yes, hate me... I believe your explanations, of course!!!!
But sometimes you NEED to be nasty.

When getting personal, like you are doing here, you need to include
at least the name of whom you reply to. Otherwise the entire forum
thinks you're calling them nasty (did you know that plural and singular
form for the second person in English are both "you"?)

I don't mind being called nasty myself, I don't don't like to fall
under a blanket occusation.
I explain why I cannot use const...

class classHolder
{
public: classHolder(classValue &ami) {}
};

class classHolder_const : public classHolder
{
public: classHolder(const classValue &ami) {}
};

classValue aValue;
const classValue aConstValue;
classHolder aHolder1 = aValue; // <= ok
classHolder aHolder2 = aConstValue; // <= forbidden
classHolder_const aHolder3 = aValue; // <= ok
classHolder_const aHolder4 = aConstValue; // <= ok

My classHolder may NOT get any const variables.

That's all fine and dandy. But if you're stuck with a certain
format of your constructors, then you have to be careful with the
return statements. You simply cannot use 'classValue()' syntax
where an instance of 'classHolder' is expected. That's all.
If you need to allow default-initialisation of 'classHolder',
just give it a default constructor. Otherwise, rethink what your
classes do and/or how they do it.

V
 
M

mlimber

Yes, hate me...

Don't be so hard on yourself. You've done nothing worthy of such scorn
and derision... yet (you don't put your open brace on the same line as
the for statement, do you?).
But sometimes you NEED to be nasty.

But if you do need to be nasty, you had better know what the
implications of your nastiness are. It appears to me that you don't.
I explain why I cannot use const...

class classHolder
{
public: classHolder(classValue &ami) {}
};

class classHolder_const : public classHolder
{
public: classHolder(const classValue &ami) {}
};

classValue aValue;
const classValue aConstValue;
classHolder aHolder1 = aValue; // <= ok
classHolder aHolder2 = aConstValue; // <= forbidden
classHolder_const aHolder3 = aValue; // <= ok
classHolder_const aHolder4 = aConstValue; // <= ok

My classHolder may NOT get any const variables.

That doesn't really explain much of anything. How are you using that
non-const reference? That's the real question here since fighting
against the rules of the language like this will likely bite you in the
end when you find you have a dangling reference. To reiterate: either
don't use a temporary or don't pass a non-const reference to
classHolder::classHolder() -- that is, either make a copy of the
classValue object or pass a const reference to it.

Cheers! --M
 
T

tthunder

H

Victor said:
When getting personal, like you are doing here, you need to include
at least the name of whom you reply to. Otherwise the entire forum
thinks you're calling them nasty (did you know that plural and singular
form for the second person in English are both "you"?)

I am really sorry!!! Big misunderstanding.
First, it was not meant personal.
Second, it was generally spoken (doing nasty C++ tricks)

And "hate me" was meant funny... because when asking question you
always get the answer: not standard => redesign
I often do things, which are not the "standard" way. Yes, I fight
against the language! But only for creating a framework, which can be
used the "standard" way.
BTW... Many design patterns use a way which is not the "standard" way.
That's all fine and dandy. But if you're stuck with a certain
format of your constructors, then you have to be careful with the
return statements. You simply cannot use 'classValue()' syntax
where an instance of 'classHolder' is expected. That's all.
If you need to allow default-initialisation of 'classHolder',
just give it a default constructor. Otherwise, rethink what your
classes do and/or how they do it.

classHolder getAHolder()
{ return classHolder (classValue());}

This compiles...
Is this ok?
Nasty trick again?
Why can't the compiler DO this itself? No you must throw an error...
 
T

tthunder

I explain why I cannot use const...
That doesn't really explain much of anything. How are you using that
non-const reference? That's the real question here since fighting
against the rules of the language like this will likely bite you in the
end when you find you have a dangling reference. To reiterate: either
don't use a temporary or don't pass a non-const reference to
classHolder::classHolder() -- that is, either make a copy of the
classValue object or pass a const reference to it.

It just explained, why I cannot use const references...
But to answer your question... in my "real code" (I constructed this..
names and everthing) the constructors are all "copy constructors". So I
copy all values without modifying anything or use references later.

Yes, therefore I could use const references, but I want to forbid the
usage of "const instances" with classHolder, but not with
classHolder_const...
 
M

mlimber

It just explained, why I cannot use const references...
But to answer your question... in my "real code" (I constructed this..
names and everthing) the constructors are all "copy constructors". So I
copy all values without modifying anything or use references later.

Yes, therefore I could use const references, but I want to forbid the
usage of "const instances" with classHolder, but not with
classHolder_const...

Finally we get down to it. Tell us more (and show us more code) about
why and how you want to do this, and then perhaps we can tell you the
best way to accomplish what you want to do.

Cheers! --M
 
V

Victor Bazarov

[...]
classHolder getAHolder()
{ return classHolder (classValue());}

This compiles...

It does???
Is this ok?

No, certainly not.
Nasty trick again?

Or a compiler bug... Or operator error...
Why can't the compiler DO this itself? No you must throw an error...

Are you sure you're using the right compiler?

----------------------------
struct A {};
struct B { B(A&) {} };
B foo() {
return B(A());
}
----------------------------
Thank you for testing your code with Comeau C/C++!
Tell others about http://www.comeaucomputing.com/tryitout !

Your Comeau C/C++ test results are as follows:

Comeau C/C++ 4.3.3 (Aug 6 2003 15:13:37) for ONLINE_EVALUATION_BETA1
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:strict errors C++

"ComeauTest.c", line 4: error: no instance of constructor "B::B" matches the
argument list
The argument types that you used are: (A)
return B(A());
^

1 error detected in the compilation of "ComeauTest.c".

In strict mode, with -tused, Compile failed
Hit the Back Button to review your code and compile options.
 
T

tthunder

mlimber said:
Finally we get down to it. Tell us more (and show us more code) about
why and how you want to do this, and then perhaps we can tell you the
best way to accomplish what you want to do.

Cheers! --M

I can only tell you more... copying code would not be possible...

think about two classes

template<typename T>
property<T>

template<typename T>
property_link<T> : public property_link_any

-----

property<T> contains values, and property_link<T> is only a "link" to a
property<T> (contains a pointer, of course).
BTW: property_link_any can link to ANY property<T>. Of course in the
real code, there are lots of compatibility checks...

Now I am linking...

property<T> myProp
const property_link<T> myLink = myProp;

ok!

using a constant version of property_link<T> I can only use
const-member-functions of property<T>. Perfect! But I can do nasty
things now...

property_link<OtherT> myOtherLink = myLink;

A kind of copy constructor is called, and myOtherLink links to the same
thing as myLink... Now imagine you COULD (just imagine... makes my
explanation easier) access T via OtherT => nothing is const now!

Therefore:
property_link<T>::property_link(property_link_any &) <= does not allow
the example
const_property_link<T>::const_property_link(const property_link_any &)
<= I want to force the usage of this class instead.

In my short example I have not mentioned the default constructor and
detailed stuff... but forget this for one moment, please... I have
managed those details already.
 

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

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top