473,287 Members | 1,947 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,287 software developers and data experts.

I want to avoid declaring a function!

Hi,
I'm having a problem with a return statement being parsed to return a
function (I think). Check here:

template <typename T> class A {};

template <typename T> class maker_of_A {
public:
A<T>& make_A() {return A<T>();};
};

template class maker_of_A<float>;

This example gives the error:

typename.cc: In member function `A<T>& maker_of_A<T>::make_A() [with T
=
float]':
typename.cc:15: instantiated from here
typename.cc:11: could not convert `{}' to `A<float>&'

I just want to return a reference to an anonymous (temporary) A<T>
object. Can I do this without creating an explicit temporary object?
KCC did what I wanted without complaining, so I've never thought about
this before... (I know the example doesn't make sense, it's adapted to
show the issue I'm having.)

Thanks,

/Patrik

Jul 23 '05 #1
14 1837
* lutorm:
I'm having a problem with a return statement being parsed to return a
function (I think). Check here:

template <typename T> class A {};

template <typename T> class maker_of_A {
public:
A<T>& make_A() {return A<T>();};
};
Returning const reference to temporary is undefined behavior;
returning non-const reference, as here, shouldn't compile.

The temporary is already destroyed when the function returns.

You're returning a reference to a non-existent object.

template class maker_of_A<float>;

This example gives the error:

typename.cc: In member function `A<T>& maker_of_A<T>::make_A() [with T
=
float]':
typename.cc:15: instantiated from here
typename.cc:11: could not convert `{}' to `A<float>&'

I just want to return a reference to an anonymous (temporary) A<T>
object.
No can do.

What you can do instead is something like

#include <memory> // std::auto_ptr

class A
{
private:
A();
public:
static std::auto_ptr<A> instance()
{
return std::auto_ptr<A>( new A );
}
};

int main()
{
std::auto_ptr<A> p = A::instance();
}

Can I do this without creating an explicit temporary object?
No, not with it, not without it.

KCC did what I wanted without complaining


Presumably it didn't.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #2
I *know* returning the non-const reference is bad. But it should be
possible, no? I should just get a warning about returning a reference
to a temporary... If I replace the definition of make_A with

A<T>& make_A() {A<T> temp; return temp;};

I get what I expected:

typename.cc: In member function `A<T>& maker_of_A<T>::make_A() [with T
=
float]':
typename.cc:15: instantiated from here
typename.cc:12: warning: reference to local variable `temp' returned

But in any case, it was just an example to illustrate what doesn't
work. I don't actually want to return by reference, I want to return by
value... Ok, here's a more true example:

#include <memory>

template <typename T> class A {
std::auto_ptr<T> a;
};

template <typename T> class maker_of_A {
public:
A<T>& make_A() {return A<T>();};
//A<T> make_A() {return A<T>();}; // alternate 1
//A<T>& make_A() {A<T> temp; return temp;}; // alternate 2
//A<T> make_A() {A<T> temp; return temp;}; // alternate 3
};

template class maker_of_A<float>;

As listed, this example gives the error:

typename.cc: In member function `A<T>& maker_of_A<T>::make_A() [with T
=
float]':
typename.cc:15: instantiated from here
typename.cc:9: could not convert `A<float>()' to `A<float>&'

Here it looks like the return tries to return a function... The
alternate 2 gives:

typename.cc: In member function `A<T>& maker_of_A<T>::make_A() [with T
=
float]':
typename.cc:15: instantiated from here
typename.cc:11: warning: reference to local variable `temp' returned

Ok, I'm down with that. But, alternate 1, which is what I actually want
to do, gives the to me completely incomprehensible error:

typename.cc: In member function `A<T> maker_of_A<T>::make_A() [with T =

float]':
typename.cc:15: instantiated from here
typename.cc:10: no matching function for call to
`A<float>::A(A<float>)'
typename.cc:3: candidates are: A<float>::A(A<float>&)

It says it's looking for a call-by-value copy constructor, but afaik
that's nonsense, such a thing doesn't exist. Alternate 3 seems to work,
and what I'm wondering is how to write alternate 1 to make it work like
alternate 3.

Thanks,

/Patrik

Jul 23 '05 #3
Actually, let me add something. Even using alternate 3 above doesn't
work if I add this at the end:

maker_of_A<float> mA;
A<float> aa=mA.make_A();

Then I get the same strange copy constructor error as before, now at
the last line. And, unfortunately, that's actually what my code looks
like, so even using alternate 3 I can't get it to compile.

/Patrik

Jul 23 '05 #4
* lutorm:
I *know* returning the non-const reference is bad.
Then keep yer dirty fingers away from it... ;-)

But it should be possible, no?
No.

A temporary is not an lvalue.

I should just get a warning about returning a reference
to a temporary...
No.
[Buried deep in other text] I don't actually want to return by reference, I want to return by
value...
In the future, to get more useful responses, try to focus on what
you'd want to achieve rather than two somethings entirely different.
[...] Ok, I'm down with that. But, alternate 1, which is what I actually want
to do, gives the to me completely incomprehensible error:

typename.cc: In member function `A<T> maker_of_A<T>::make_A() [with T =

float]':
typename.cc:15: instantiated from here
typename.cc:10: no matching function for call to
`A<float>::A(A<float>)'
typename.cc:3: candidates are: A<float>::A(A<float>&)

It says it's looking for a call-by-value copy constructor, but afaik
that's nonsense, such a thing doesn't exist.
The compiler is looking for a copy constructor.

This error message does not correspond to the code you posted (snipped).

In the actual code you have defined a constructor for A.

In the future, to get more useful responses, post the actual code
rather than fantasy code.

Sorry for the harsh tone, but you've led me and possibly others on
a wild goose trip, wasting our time, and, at least I tend to get a
teeny tiny bit _irritated_ when someone does that.

Alternate 3 seems to work,
and what I'm wondering is how to write alternate 1 to make it work like
alternate 3.


In the future, to get more useful responses, post the actual code
rather than fantasy code.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #5
On 2005-05-23, lutorm <pa****@ucolick.org> wrote:
I *know* returning the non-const reference is bad. But it should be
possible, no?
No, because the temporary is an r-value, the reference is an l-value. You're trying
to initialize an l-value (the reference you're returning) with an r-value (the
temporary).
I should just get a warning about returning a reference
to a temporary... If I replace the definition of make_A with

A<T>& make_A() {A<T> temp; return temp;};

I get what I expected:

typename.cc: In member function `A<T>& maker_of_A<T>::make_A() [with T
=
float]':
typename.cc:15: instantiated from here
typename.cc:12: warning: reference to local variable `temp' returned
temp is not an r-value in the same sense as the result of an expression is.

For example, you can't do this: (a+b) += 1;
but you can do: c = a+b; c += 1;
But in any case, it was just an example to illustrate what doesn't
work. I don't actually want to return by reference, I want to return by
value... Ok, here's a more true example:

#include <memory>

template <typename T> class A {
std::auto_ptr<T> a;
};

template <typename T> class maker_of_A {
public:
A<T>& make_A() {return A<T>();};
//A<T> make_A() {return A<T>();}; // alternate 1
//A<T>& make_A() {A<T> temp; return temp;}; // alternate 2
//A<T> make_A() {A<T> temp; return temp;}; // alternate 3
};

template class maker_of_A<float>;

As listed, this example gives the error:

typename.cc: In member function `A<T>& maker_of_A<T>::make_A() [with T
=
float]':
typename.cc:15: instantiated from here
typename.cc:9: could not convert `A<float>()' to `A<float>&'
Same deal. You're trying to initialize a non-const reference with the result of
an expression. BTW, it doesn't help you much anyway. The return type should be
A<T>.
Ok, I'm down with that. But, alternate 1, which is what I actually want
to do, gives the to me completely incomprehensible error:

typename.cc: In member function `A<T> maker_of_A<T>::make_A() [with T =

float]':
typename.cc:15: instantiated from here
typename.cc:10: no matching function for call to
`A<float>::A(A<float>)'
typename.cc:3: candidates are: A<float>::A(A<float>&)

It says it's looking for a call-by-value copy constructor, but afaik
that's nonsense, such a thing doesn't exist.


Same deal. You're *still* trying to initialize a non-const reference (the
A<float>& argument) with a temporary. Could you please stop doing that ?
Usually, you'd get away with it because the copy-constructor would take a
const reference argument, but because you're aggregating auto_ptr, it wants
a non-const reference. And that non-const reference can't be initialized by
an r-value temporary.

Cheers,
--
Donovan Rebbechi
http://pegasus.rutgers.edu/~elflord/
Jul 23 '05 #6
lutorm wrote:
I *know* returning the non-const reference is bad. But it should be
possible, no?
No.
I should just get a warning about returning a reference to a temporary...
If you return a const reference, you might get a warning, because returning
a reference to a local variable makes no sense. The variable will be gone
before the reference to it can be used. So DON'T DO IT!
If I replace the definition of make_A with

A<T>& make_A() {A<T> temp; return temp;};

I get what I expected:

typename.cc: In member function `A<T>& maker_of_A<T>::make_A() [with T
=
float]':
typename.cc:15: instantiated from here
typename.cc:12: warning: reference to local variable `temp' returned
temp is not a temporary, so you can bind it to a non-const reference.
But in any case, it was just an example to illustrate what doesn't
work. I don't actually want to return by reference, I want to return by
value...
If you want that, then do it.
Ok, here's a more true example:

#include <memory>

template <typename T> class A {
std::auto_ptr<T> a;
};

template <typename T> class maker_of_A {
public:
A<T>& make_A() {return A<T>();};
//A<T> make_A() {return A<T>();}; // alternate 1
//A<T>& make_A() {A<T> temp; return temp;}; // alternate 2
//A<T> make_A() {A<T> temp; return temp;}; // alternate 3
};

template class maker_of_A<float>;

As listed, this example gives the error:

typename.cc: In member function `A<T>& maker_of_A<T>::make_A() [with T
=
float]':
typename.cc:15: instantiated from here
typename.cc:9: could not convert `A<float>()' to `A<float>&'
You cannot bind a non-const reference (A<float>&) to a temporary
(A<float>()).
Here it looks like the return tries to return a function...
No, it doesn't.
The alternate 2 gives:

typename.cc: In member function `A<T>& maker_of_A<T>::make_A() [with T
=
float]':
typename.cc:15: instantiated from here
typename.cc:11: warning: reference to local variable `temp' returned

Ok, I'm down with that. But, alternate 1, which is what I actually want
to do, gives the to me completely incomprehensible error:

typename.cc: In member function `A<T> maker_of_A<T>::make_A() [with T =

float]':
typename.cc:15: instantiated from here
typename.cc:10: no matching function for call to
`A<float>::A(A<float>)'
typename.cc:3: candidates are: A<float>::A(A<float>&)

It says it's looking for a call-by-value copy constructor,
That's a bit misleading.
but afaik that's nonsense, such a thing doesn't exist.
The problem is that the compiler-generated copy constructor takes a
reference to non-const, and again, such a reference cannot be initialized
with a temporary.
The reason that is that your member variable is an auto_ptr. That class is
kind of special with regard to copying, because the copy constructor will
change the original, and so its copy constructor takes a non-const
reference. Therefore, your class's compiler generated copy constructor also
must take a non-const reference.
Alternate 3 seems to work, and what I'm wondering is how to write
alternate 1 to make it work like alternate 3.


For that, you need to replace the auto_ptr member with something that
doesn't change the original on copying.

Jul 23 '05 #7
Alf P. Steinbach wrote:
typename.cc: In member function `A<T> maker_of_A<T>::make_A() [with T =

float]':
typename.cc:15: instantiated from here
typename.cc:10: no matching function for call to
`A<float>::A(A<float>)'
typename.cc:3: candidates are: A<float>::A(A<float>&)

It says it's looking for a call-by-value copy constructor, but afaik
that's nonsense, such a thing doesn't exist.
The compiler is looking for a copy constructor.

This error message does not correspond to the code you posted (snipped).


Look again. It does correspond.
In the actual code you have defined a constructor for A.
Ever heard of compiler-generated copy constructors? ;-)
In the future, to get more useful responses, post the actual code
rather than fantasy code.

Sorry for the harsh tone, but you've led me and possibly others on
a wild goose trip, wasting our time, and, at least I tend to get a
teeny tiny bit _irritated_ when someone does that.


Open an editor window and write into it 100 times: "I won't slam down others
without previously checking whether they are wrong or I am". And don't use
copy/paste!

Jul 23 '05 #8
* Rolf Magnus:
Alf P. Steinbach wrote:
typename.cc: In member function `A<T> maker_of_A<T>::make_A() [with T =

float]':
typename.cc:15: instantiated from here
typename.cc:10: no matching function for call to
`A<float>::A(A<float>)'
typename.cc:3: candidates are: A<float>::A(A<float>&)

It says it's looking for a call-by-value copy constructor, but afaik
that's nonsense, such a thing doesn't exist.


The compiler is looking for a copy constructor.

This error message does not correspond to the code you posted (snipped).


Look again. It does correspond.


So it does, with a slight commenting out and commenting in.

In the actual code you have defined a constructor for A.


Ever heard of compiler-generated copy constructors? ;-)


That's why I thought there was a defined constructor, yes.

My backpropagating neural network visual filter removed the meaningless
auto_ptr he'd _added_ in there this time.

Check the original posting.

In the future, to get more useful responses, post the actual code
rather than fantasy code.

Sorry for the harsh tone, but you've led me and possibly others on
a wild goose trip, wasting our time, and, at least I tend to get a
teeny tiny bit _irritated_ when someone does that.


Open an editor window and write into it 100 times: "I won't slam down others
without previously checking whether they are wrong or I am". And don't use
copy/paste!


Nah, the OP is wrong as can be possibly be, not to say wrong-headed; he
got a perfectly good answer (from me ;-) ) the first time around, regarding
the question as then posed, including an example of what he should/could do,
and then I had to waste time figuring out that he simply _ignored_ that.

And I don't like that kind of chase.

I'm not sure whether I agree with advice about not using copy/paste. If you
mean, don't use manual copy/paste, use the editor's repeat function, well,
OK. I can go with that.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #9
Alf P. Steinbach wrote:
> The compiler is looking for a copy constructor.
>
> This error message does not correspond to the code you posted
> (snipped).
Look again. It does correspond.


So it does, with a slight commenting out and commenting in.


Yes, and the OP described that.
> In the actual code you have defined a constructor for A.


Ever heard of compiler-generated copy constructors? ;-)


That's why I thought there was a defined constructor, yes.

My backpropagating neural network visual filter removed the meaningless
auto_ptr he'd _added_ in there this time. Check the original posting.


It is not at all meaningless. It explains why the OP can't return by value,
which was (according to his second posting) what he actually wanted. Maybe
he just left it out in the first posting because he _thought_ it would be
meaningless. After all, when returning a reference, it actually is
meaningless.
> In the future, to get more useful responses, post the actual code
> rather than fantasy code.
>
> Sorry for the harsh tone, but you've led me and possibly others on
> a wild goose trip, wasting our time, and, at least I tend to get a
> teeny tiny bit _irritated_ when someone does that.


Open an editor window and write into it 100 times: "I won't slam down
others without previously checking whether they are wrong or I am". And
don't use copy/paste!


Nah, the OP is wrong as can be possibly be, not to say wrong-headed; he
got a perfectly good answer (from me ;-) ) the first time around,


However, you were wrong when writing that the output doesn't correspond to
the error message. I admit that this can happen quickly if the OP suddenly
sneaks in some seemingly unimportant thing ;-)
regarding the question as then posed, including an example of what he
should/could do,
I think the OP didn't give enough information to know whether your example
is a solution or not.
and then I had to waste time figuring out that he simply _ignored_ that.
It seems to me that he originally wanted to return by value. He didn't
succeed, and didn't understand why, so he tried to return by reference,
which also didn't work. Then he asked for the reason of that second
problem. Of course, it would have been better to ask about the first
problem directly.
And I don't like that kind of chase.

I'm not sure whether I agree with advice about not using copy/paste. If
you mean, don't use manual copy/paste, use the editor's repeat function,
well, OK. I can go with that.


Don't start arguing, or I will make that 200 ;-)

Jul 23 '05 #10
* lutorm:

So I've gathered that the problem is the auto_ptr copy constructor
taking a non-const reference. But I'm still unclear how to make my code
work. How can I then *ever* return an instance of a class containing an
auto_ptr, if calling return tries to do an illegal bad call to the copy
constructor with a reference to a temporary? (I tried creating a copy
constructor for A that also takes a non-const reference but that made
no diff.)
You can

1) Use the code shown in my first reply, i.e. dynamic allocation.

2) Return a reference or pointer to a non-temporary non-local object.
For example, if this is a singleton.
This is what I want to do: maker_of_A::make_A() creates an instance of
A (which contains an auto_ptr) and should return that instance (or a
copy of it). Is this possible?
See my first reply in this thread.

For completeness, here is the full example of what I'm trying to do:

#include <memory>

template <typename T> class A { // ray distribution pair
std::auto_ptr<T> a;
public:
A() {};
A(A& rhs) : a(rhs.a) {};
};
What is the purpose of the auto_ptr member?

template <typename T> class maker_of_A { // emission
public:
A<T> make_A() {A<T> temp; return temp;}; // alternate 3
};
maker_of_A<float> mA;
A<float> aa=mA.make_A();


It seems all you want to do is to have a convenient notation to "name"
the particular initialization employed.

Perhaps the "named constructor idiom" can help you?

With this you move your maker_of_A code into A constructors. See FAQ item
10.8, at <url: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8>.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #11
* Victor Bazarov:
Donovan Rebbechi wrote:
On 2005-05-23, lutorm <pa****@ucolick.org> wrote:
I *know* returning the non-const reference is bad. But it should be
possible, no?

No, because the temporary is an r-value, the reference is an l-value. You're trying
to initialize an l-value (the reference you're returning) with an r-value (the
temporary).


A temporary is only an r-value if it's of one of built-in types. If it
is a UDT, it's an l-value.


Sorry.

§3.10 in general and §3.10/2 note 47 for the quick summary relevant here:
"Expressions such as invocations of constructors and of functions that
return a class type refers to objects, and the implementation can invoke a
member function upon such objects, but the expressions are not lvalues".

What's prohibited there is to bind a reference
to non-const object to a temporary. L-value-ness has nothing to do with
that. Just FYI.


Sorry.

§8.5.3/5, the rules for reference initialization, divides the cases into
lvalues and rvalues.
[...]
For example, you can't do this: (a+b) += 1;


Yes, you can if 'a+b' returns a temporary of a class type which defines
the += operator.


Yep, I think so too.

There is a special rule, §3.10/10, allowing member functions to be called on
rvalues, which include temporary objects.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #12
* Alf P. Steinbach:

It seems all you want to do is to have a convenient notation to "name"
the particular initialization employed.

Perhaps the "named constructor idiom" can help you?

With this you move your maker_of_A code into A constructors. See FAQ item
10.8, at <url: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8>.


Sorry, I didn't read that FAQ item before directing you to it.

It just had the title, not the relevant content for your particular case.

Here's one way to provide named constructors that will work for your case:

struct AsPolar {};
struct AsCartesian {};

class Complex
{
private:
// whatever
public:
Complex( AsCartesian, double x, double y );
Complex( AsPolar, double radius, double angle );
};

...
Complex c( AsCartesian(), 1.2, 5.7 );

All assuming that named constructors is what you're after.

Otherwise, what's the point of the factory class?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #13
Alf P. Steinbach wrote:
You can

1) Use the code shown in my first reply, i.e. dynamic allocation.

2) Return a reference or pointer to a non-temporary non-local object. For example, if this is a singleton.
This is what I want to do: maker_of_A::make_A() creates an instance of A (which contains an auto_ptr) and should return that instance (or a copy of it). Is this possible?
See my first reply in this thread.

For completeness, here is the full example of what I'm trying to do:
#include <memory>

template <typename T> class A { // ray distribution pair
std::auto_ptr<T> a;
public:
A() {};
A(A& rhs) : a(rhs.a) {};
};


What is the purpose of the auto_ptr member?


Class A is actually a larger class, containing several members. It's
used as a container for the make_A method to return several quantities.
The auto_ptr is used to hold a particularly large object that I don't
want to copy-by-value all the time (not just in make_A but in its
subsequent usage).
It seems all you want to do is to have a convenient notation to "name" the particular initialization employed.

Perhaps the "named constructor idiom" can help you?


Perhaps. Class maker_of_A is not just a maker of A, it's a large class
which holds its own information about something (not relevant for this
discussion), but one of the things it does is to use this information
to generate A's. It's not its primary function, but an essential one.
I don't see how the "named constructors" apply to this case. Maker_of_A
can't use a static function to do it because different makers_of_A
contain different data and make different A's. The problem is not
convenience, it's to get the A object out of make_A.

I guess, as you say, I can dynamically allocate the A and return IT
through an auto_ptr. It does seem very circuitous, though. Is the
statement that it's impossible to return an object containing an
auto_ptr by value true? It seems bizarre to me... Correct me if I'm
wrong, but in principle it doesn't seem to be anything wrong with doing
this? As I understand, this is what happens when make_A() is called:

1. create A-object temp
2. when returning from make_A(), call "aa.A::A(A& temp)" to copy
construct aa from temp
3. destroy temp

it doesn't seem like there's anything wrong with any of these steps.
temp isn't destroyed until the copy constructor has completed. I mean,
it works to return auto_ptrs by value, so why not an object containing
an auto_ptr?

sorry for belabouring this, but I'd like to understand exactly why this
is forbidden and why it makes sense that it is.

Jul 23 '05 #14
* lutorm:
Is the statement that it's impossible to return an object containing an
auto_ptr by value true?
No.

#include <memory>

class Bad
{
private:
std::auto_ptr<int> p;
Bad() {};
public:
static Bad instance()
{
Bad result;
return result;
}
};

int main()
{
Bad::instance();
}

Here the compiler-generated copy constructor has (of necessity, due to the
auto_ptr which modifies the source in a copy) non-const argument.

However, because of that non-const argument you cannot write

Bad o( Bad::instance() );

or

Bad o = Bad::instance();

because that requires a copy constructor with const argument, because a
temporary is an rvalue and and an rvalue, such as the number 42, is not
something you'd ordinarily want to modify, so it doesn't match the non-
const reference argument.

So even though you can return the value, the caller cannot use it directly
to initialize a variable -- at least not without breaking const
correctness.

It seems bizarre to me... Correct me if I'm
wrong, but in principle it doesn't seem to be anything wrong with doing
this? As I understand, this is what happens when make_A() is called:

1. create A-object temp
2. when returning from make_A(), call "aa.A::A(A& temp)" to copy
construct aa from temp
3. destroy temp

it doesn't seem like there's anything wrong with any of these steps.
temp isn't destroyed until the copy constructor has completed. I mean,
it works to return auto_ptrs by value, so why not an object containing
an auto_ptr?
std::auto_ptr uses very dirty hacks to allow something that _looks like_
copy construction -- but isn't, really.

Let's examine a concrete case,

#include <memory>

int main()
{
std::auto_ptr<int> x = std::auto_ptr<int>( 0 );
}

Which constructor is involved here (assuming the compiler doesn't
optimize away the temporary, which I think it's allowed to do)?

One would guess the copy constructor with const argument, but if so then
it would break const correctness.

Instead, what happens is logically equivalent to (1) a conversion of the
temporary to std::auto_ptr_ref, and (2) use of that std::auto_ptr_ref
object as argument to the destination std::auto_ptr object's constructor.

(1) is allowed because you're allowed to call member functions, such as
conversion operators, on temporary objects, and (2) is just the usual, so
that the code above is logically equivalent to

#include <memory>

int main()
{
std::auto_ptr<int> temp( 0 );
std::auto_ptr_ref<int> ref( temp );
std::auto_ptr<int> x( ref );
}

So, you _can_, in principle, use this dirty technique yourself:

#include <memory>

class ARef
{
friend class A;
private:
A* myRef;
A& object() { return *myRef; }
public:
ARef( A& aRef ): myRef( &aRef ) {}
};

class A
{
friend class maker_of_A;
private:
std::auto_ptr<float> a;
A(){};
public:
A( ARef ref ): a( ref.object().a ) {}
operator ARef() { return ARef( *this ); }
};

class maker_of_A
{
public:
A instance() { return A(); }
};

int main()
{
A o = maker_of_A().instance();
}

And here you see more clearly what's going on: copying is implemented by
turning a reference into a pointer (which can be copied by assignment),
and back again, and the source of the copy operation is modified by the
auto_ptr in there.

There has been some debate about whether it's really allowed, because
seemingly there are _two_ user-defined conversions involved. I'm not sure
about the consensus for that, but I know there are fancy implementations
of something like std::auto_ptr that are said to be somehow more conforming.
Anyway, it works in practice, but it's very dirty.

sorry for belabouring this, but I'd like to understand exactly why this
is forbidden and why it makes sense that it is.


Not forbidden, but made hard, because in a logical copy operation one does
not really expect the object being copied to be changed, and it's much
better that the language helps out to _ensure_ that that doesn't happen by
accident -- you should really Really REALLY know what you're doing.
Disclaimer: writing this at the go-to-bed-soon stage of my day, so there may
be slightly incorrect or even untrue statements up there; I trust somebody
will correct things if so.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 23 '05 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

15
by: Bob | last post by:
I've tried everything; and I can't seem to get past this VERY (seemingly) simply problem. I want to work with an array variable within a function(s). I can't get it to work; if I: 1) global...
3
by: LinusLee | last post by:
class CAnalyzer { // attribute private: public: // behavior private: void NullFunc(NODE *pNode); void TraverseNode(NODE* pNode, void (*preFunc)(NODE *node), void (*postFunc)(NODE *node));
17
by: Pushkar Pradhan | last post by:
I want to time my matrix multiply code (in MFLOPS). I want to run the code 100,000 times or some other big number. This can be done 2 ways (for and while loops): timer1 = time(NULL); for(n = 0;...
16
by: G Patel | last post by:
Hi, If I want to call functions that don't return int without declaring them, will there be any harm? I only want to assign the function(return value) to the type that it returns, so I don't...
3
by: tomb | last post by:
VS2005. It's possible to avoid circular references like in C++?
18
by: StephQ | last post by:
I'm facing the following problem: I'm using the Gnu Scientific Library (it is a C math library), and in particular random number generation algorithms. Example code is: .... gsl_rng * r; .......
8
by: =?Utf-8?B?UHVjY2E=?= | last post by:
Hi, I'm using vs2005, .net 2, C# for Windows application. I use DllImport so I can call up a function written in C++ as unmanaged code and compiled as a dll us vs2005. My application is able to...
5
by: Rahul B | last post by:
Hi, I have very little knowledge about creating Procedures/functions in DB2. When i tried to create the test function like CREATE FUNCTION GET_TEST (P_TEST_ID INTEGER, P_SEL_OR_SORT...
8
by: nguillot | last post by:
Hello. If I have the following classes: class B {}; typedef B tB; if A is: class A
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.