Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > passing ref to ptr again as ref to ptr....

Reply
Thread Tools

passing ref to ptr again as ref to ptr....

 
 
osama178@gmail.com
Guest
Posts: n/a
 
      04-24-2008
Let's say I have this code

--------------------
class GenericQueue
{
public:
bool Pop(void*& refToPtr); // //--------------------(1)

};

class SpecialQueue: private GenericQueue
{
public:
bool Pop(T*& refToPtr)
{
return
GenericQueue:op(refToPtr); //--------------------(2)
}

};


Why doesn't the statement in -------(2) compile?
 
Reply With Quote
 
 
 
 
osama178@gmail.com
Guest
Posts: n/a
 
      04-24-2008
On Apr 24, 1:37 pm, (E-Mail Removed) wrote:
> Let's say I have this code
>
> --------------------
> class GenericQueue
> {
> public:
> bool Pop(void*& refToPtr); // //--------------------(1)
>
> };
>
> class SpecialQueue: private GenericQueue
> {
> public:
> bool Pop(T*& refToPtr)
> {
> return
> GenericQueue:op(refToPtr); //--------------------(2)
> }
>
> };
>
> Why doesn't the statement in -------(2) compile?



And I did have the

template<class T> in front of SpecialClass. Sorry!. I just posted a
snippet here.
 
Reply With Quote
 
 
 
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      04-25-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> On Apr 24, 1:37 pm, (E-Mail Removed) wrote:
>> Let's say I have this code
>>
>> --------------------
>> class GenericQueue
>> {
>> public:
>> bool Pop(void*& refToPtr); // //--------------------(1)
>>
>> };
>>
>> class SpecialQueue: private GenericQueue
>> {
>> public:
>> bool Pop(T*& refToPtr)
>> {
>> return
>> GenericQueue:op(refToPtr); //--------------------(2)
>> }
>>
>> };
>>
>> Why doesn't the statement in -------(2) compile?


Because T*& and void*& are different types with no automatic conversions
between them.

> And I did have the
>
> template<class T> in front of SpecialClass. Sorry!. I just posted a
> snippet here.


Why do you run your own code for queue? It seems as though std::queue<T*>
might be what you are looking for.


Best

Kai-Uwe Bux
 
Reply With Quote
 
osama178@gmail.com
Guest
Posts: n/a
 
      04-25-2008
On Apr 24, 7:14 pm, Kai-Uwe Bux <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > On Apr 24, 1:37 pm, (E-Mail Removed) wrote:
> >> Let's say I have this code

>
> >> --------------------
> >> class GenericQueue
> >> {
> >> public:
> >> bool Pop(void*& refToPtr); // //--------------------(1)

>
> >> };

>
> >> class SpecialQueue: private GenericQueue
> >> {
> >> public:
> >> bool Pop(T*& refToPtr)
> >> {
> >> return
> >> GenericQueue:op(refToPtr); //--------------------(2)
> >> }

>
> >> };

>
> >> Why doesn't the statement in -------(2) compile?

>
> Because T*& and void*& are different types with no automatic conversions
> between them.
>
> > And I did have the

>
> > template<class T> in front of SpecialClass. Sorry!. I just posted a
> > snippet here.

>
> Why do you run your own code for queue? It seems as though std::queue<T*>
> might be what you are looking for.
>
> Best
>
> Kai-Uwe Bux


I am implementing a lockless queue, which I don't think the
std::queue<T*> provides. To avoid template-induced code bloat, I am
implementing a generic the queue using void* pointers. But to gain
type-safety, I am implementing a templated interface-class.

Now what is confusing me is that this function works


SpecialQueue:ush(T* ptr) { GenericQueue:ush(ptr); }

and it converts T* to void* no problem.

But when I do

SpecialQueue:op(T*& refPtr) { GenericQueue:op(refPtr); }

Now let's say I instantiate an object

SpecialQueue<int> spQ();
int a = 10;
int p = &a;
spQ.Pop(p);

It gives me this error:

"cannot convert parameter 1 from 'int *' to 'void *&'"
 
Reply With Quote
 
osama178@gmail.com
Guest
Posts: n/a
 
      04-25-2008
On Apr 24, 7:14 pm, Kai-Uwe Bux <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > On Apr 24, 1:37 pm, (E-Mail Removed) wrote:
> >> Let's say I have this code

>
> >> --------------------
> >> class GenericQueue
> >> {
> >> public:
> >> bool Pop(void*& refToPtr); // //--------------------(1)

>
> >> };

>
> >> class SpecialQueue: private GenericQueue
> >> {
> >> public:
> >> bool Pop(T*& refToPtr)
> >> {
> >> return
> >> GenericQueue:op(refToPtr); //--------------------(2)
> >> }

>
> >> };

>
> >> Why doesn't the statement in -------(2) compile?

>
> Because T*& and void*& are different types with no automatic conversions
> between them.


Sorry. Why don't we need automatic type conversion from T* to void*
but need it from T*& to void*&.
I am still learning C++, so please excuse my ignorance.
 
Reply With Quote
 
Bo Persson
Guest
Posts: n/a
 
      04-25-2008
(E-Mail Removed) wrote:
> On Apr 24, 7:14 pm, Kai-Uwe Bux <(E-Mail Removed)> wrote:
>> (E-Mail Removed) wrote:
>>> On Apr 24, 1:37 pm, (E-Mail Removed) wrote:
>>>> Let's say I have this code

>>
>>>> --------------------
>>>> class GenericQueue
>>>> {
>>>> public:
>>>> bool Pop(void*& refToPtr); // //--------------------(1)

>>
>>>> };

>>
>>>> class SpecialQueue: private GenericQueue
>>>> {
>>>> public:
>>>> bool Pop(T*& refToPtr)
>>>> {
>>>> return
>>>> GenericQueue:op(refToPtr); //--------------------(2)
>>>> }

>>
>>>> };

>>
>>>> Why doesn't the statement in -------(2) compile?

>>
>> Because T*& and void*& are different types with no automatic
>> conversions between them.
>>
>>> And I did have the

>>
>>> template<class T> in front of SpecialClass. Sorry!. I just posted
>>> a snippet here.

>>
>> Why do you run your own code for queue? It seems as though
>> std::queue<T*> might be what you are looking for.
>>
>> Best
>>
>> Kai-Uwe Bux

>
> I am implementing a lockless queue, which I don't think the
> std::queue<T*> provides. To avoid template-induced code bloat, I am
> implementing a generic the queue using void* pointers.


And you believe you can outsmart the compiler?

I wouldn't bet on that.


Bo Persson


 
Reply With Quote
 
osama178@gmail.com
Guest
Posts: n/a
 
      04-25-2008
On Apr 25, 12:48 pm, "Bo Persson" <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > On Apr 24, 7:14 pm, Kai-Uwe Bux <(E-Mail Removed)> wrote:
> >> (E-Mail Removed) wrote:
> >>> On Apr 24, 1:37 pm, (E-Mail Removed) wrote:
> >>>> Let's say I have this code

>
> >>>> --------------------
> >>>> class GenericQueue
> >>>> {
> >>>> public:
> >>>> bool Pop(void*& refToPtr); // //--------------------(1)

>
> >>>> };

>
> >>>> class SpecialQueue: private GenericQueue
> >>>> {
> >>>> public:
> >>>> bool Pop(T*& refToPtr)
> >>>> {
> >>>> return
> >>>> GenericQueue:op(refToPtr); //--------------------(2)
> >>>> }

>
> >>>> };

>
> >>>> Why doesn't the statement in -------(2) compile?

>
> >> Because T*& and void*& are different types with no automatic
> >> conversions between them.

>
> >>> And I did have the

>
> >>> template<class T> in front of SpecialClass. Sorry!. I just posted
> >>> a snippet here.

>
> >> Why do you run your own code for queue? It seems as though
> >> std::queue<T*> might be what you are looking for.

>
> >> Best

>
> >> Kai-Uwe Bux

>
> > I am implementing a lockless queue, which I don't think the
> > std::queue<T*> provides. To avoid template-induced code bloat, I am
> > implementing a generic the queue using void* pointers.

>
> And you believe you can outsmart the compiler?
>
> I wouldn't bet on that.
>
> Bo Persson


Why not?

If you instantiate GenericQueue a dozen times, you'll have a dozen
copies of its code. But if you use GenericQueue for storing void*
pointers instead, make its ctor, copy ctor, and assig operator
private, you'll prevent clients from making instances of it AND you'll
have only one version of the code. And the templated interface class
will implement its functionality in-terms-of GenericQueue
functionality and provide for type safety. The code in the interface
class is substantially less than that of the GenericQueue and will not
result in as much code bloat. No?

Of course I'll have to account for the fact that a pointer to an
object might have been pushed onto multiple stacks.

 
Reply With Quote
 
osama178@gmail.com
Guest
Posts: n/a
 
      04-25-2008
On Apr 25, 1:09 pm, (E-Mail Removed) wrote:
> On Apr 25, 12:48 pm, "Bo Persson" <(E-Mail Removed)> wrote:
>
>
>
> > (E-Mail Removed) wrote:
> > > On Apr 24, 7:14 pm, Kai-Uwe Bux <(E-Mail Removed)> wrote:
> > >> (E-Mail Removed) wrote:
> > >>> On Apr 24, 1:37 pm, (E-Mail Removed) wrote:
> > >>>> Let's say I have this code

>
> > >>>> --------------------
> > >>>> class GenericQueue
> > >>>> {
> > >>>> public:
> > >>>> bool Pop(void*& refToPtr); // //--------------------(1)

>
> > >>>> };

>
> > >>>> class SpecialQueue: private GenericQueue
> > >>>> {
> > >>>> public:
> > >>>> bool Pop(T*& refToPtr)
> > >>>> {
> > >>>> return
> > >>>> GenericQueue:op(refToPtr); //--------------------(2)
> > >>>> }

>
> > >>>> };

>
> > >>>> Why doesn't the statement in -------(2) compile?

>
> > >> Because T*& and void*& are different types with no automatic
> > >> conversions between them.

>
> > >>> And I did have the

>
> > >>> template<class T> in front of SpecialClass. Sorry!. I just posted
> > >>> a snippet here.

>
> > >> Why do you run your own code for queue? It seems as though
> > >> std::queue<T*> might be what you are looking for.

>
> > >> Best

>
> > >> Kai-Uwe Bux

>
> > > I am implementing a lockless queue, which I don't think the
> > > std::queue<T*> provides. To avoid template-induced code bloat, I am
> > > implementing a generic the queue using void* pointers.

>
> > And you believe you can outsmart the compiler?

>
> > I wouldn't bet on that.

>
> > Bo Persson

>
> Why not?
>
> If you instantiate GenericQueue a dozen times, you'll have a dozen
> copies of its code. But if you use GenericQueue for storing void*
> pointers instead, make its ctor, copy ctor, and assig operator
> private, you'll prevent clients from making instances of it AND you'll
> have only one version of the code. And the templated interface class
> will implement its functionality in-terms-of GenericQueue
> functionality and provide for type safety. The code in the interface
> class is substantially less than that of the GenericQueue and will not
> result in as much code bloat. No?
>
> Of course I'll have to account for the fact that a pointer to an
> object might have been pushed onto multiple stacks.


The idea is from Scott Myer's "Effective C++", Item 42 - Use Private
Inheritance Judiciously.
 
Reply With Quote
 
Ivan Vecerina
Guest
Posts: n/a
 
      04-26-2008
<(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
: I am implementing a lockless queue, which I don't think the
: std::queue<T*> provides. To avoid template-induced code bloat, I am
: implementing a generic the queue using void* pointers. But to gain
: type-safety, I am implementing a templated interface-class.

This is a common optimization technique indeed (used back in early
C++ times). But keep in mind that, nowadays, some compilers/linkers
are able to automatically eliminate redundant copies of the same
code, such as those resulting from multiple template instantiations.

: Now what is confusing me is that this function works
:
:
: SpecialQueue:ush(T* ptr) { GenericQueue:ush(ptr); }
:
: and it converts T* to void* no problem.

Indeed: the compiler passes a *copy* of ptr to the generic function.
During this copy, it can make an implicit conversion from T* to void*.

: But when I do
:
: SpecialQueue:op(T*& refPtr) { GenericQueue:op(refPtr); }
....
: It gives me this error:
:
: "cannot convert parameter 1 from 'int *' to 'void *&'"

Mind the fact that the int* and void* may have different
in-memory representations (even though this is not the case
on the common processor architectures that you and I use).
You can force the behavior you are looking for by using an
explicit cast:
SpecialQueue:op(T*& refPtr)
{ GenericQueue:op(reinterpret_cast<void*&>(refPtr) ); }
However, this will result in undefined behavior, even though
problems will only happen in "exotic" platforms. It will work
perfectly fine on most architectures, but is not portable.

In proper and portable C++, you would need to write:
bool SpecialQueue:op(T*& refPtr)
{
void * ptr; // I assume this is an output-only parameter
bool const result = GenericQueue:op(&ptr);
refPtr = static_cast<T*>(ptr); // ok, works if the
// previously pushed pointer was indeed a T* or NULL
// ( any T* can be converted to void* and then back )
return result;
}


As you see, C++ only allows the implicit conversions that are safe.
(except for those (many) that were inherited from C...)

Cheers -Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Brainbench MVP for C++ <> http://www.brainbench.com

 
Reply With Quote
 
Bo Persson
Guest
Posts: n/a
 
      04-26-2008
(E-Mail Removed) wrote:
> On Apr 25, 12:48 pm, "Bo Persson" <(E-Mail Removed)> wrote:
>> (E-Mail Removed) wrote:
>>> On Apr 24, 7:14 pm, Kai-Uwe Bux <(E-Mail Removed)> wrote:
>>>> (E-Mail Removed) wrote:
>>>>> On Apr 24, 1:37 pm, (E-Mail Removed) wrote:
>>>>>> Let's say I have this code

>>
>>>>>> --------------------
>>>>>> class GenericQueue
>>>>>> {
>>>>>> public:
>>>>>> bool Pop(void*& refToPtr); // //--------------------(1)

>>
>>>>>> };

>>
>>>>>> class SpecialQueue: private GenericQueue
>>>>>> {
>>>>>> public:
>>>>>> bool Pop(T*& refToPtr)
>>>>>> {
>>>>>> return
>>>>>> GenericQueue:op(refToPtr); //--------------------(2)
>>>>>> }

>>
>>>>>> };

>>
>>>>>> Why doesn't the statement in -------(2) compile?

>>
>>>> Because T*& and void*& are different types with no automatic
>>>> conversions between them.

>>
>>>>> And I did have the

>>
>>>>> template<class T> in front of SpecialClass. Sorry!. I just
>>>>> posted a snippet here.

>>
>>>> Why do you run your own code for queue? It seems as though
>>>> std::queue<T*> might be what you are looking for.

>>
>>>> Best

>>
>>>> Kai-Uwe Bux

>>
>>> I am implementing a lockless queue, which I don't think the
>>> std::queue<T*> provides. To avoid template-induced code bloat, I
>>> am implementing a generic the queue using void* pointers.

>>
>> And you believe you can outsmart the compiler?
>>
>> I wouldn't bet on that.
>>
>> Bo Persson

>
> Why not?
>
> If you instantiate GenericQueue a dozen times, you'll have a dozen
> copies of its code.


No, you will probably not.

On the compiler I use, templates will most often share code for
objects of the same size, as the linker will merge identical code
blocks. For example,

struct two
{
short x;
short y;
};

std::vector<int> v1;
std::vector<long> v2;
std::vector<two> v3;

will only generate one set of code in the resulting .exe file.


> But if you use GenericQueue for storing void*
> pointers instead, make its ctor, copy ctor, and assig operator
> private, you'll prevent clients from making instances of it AND
> you'll have only one version of the code. And the templated
> interface class will implement its functionality in-terms-of
> GenericQueue functionality and provide for type safety. The code in
> the interface class is substantially less than that of the
> GenericQueue and will not result in as much code bloat. No?


Or it will possibly add to the code size by adding another layer. At
least it will add to the complexity of the code.


Bo Persson


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
passing ref to ptr again as ref to ptr.... osama178@gmail.com C++ 6 04-29-2008 08:09 AM
passing ref to ptr again as ref to ptr.... osama178@gmail.com C++ 0 04-24-2008 08:23 PM
const ptr to const ptr ? franco ziade C Programming 3 02-17-2005 04:30 AM
How to convert a double **ptr in a double const ** const ptr? Heiko Vogel C Programming 3 09-14-2004 10:23 AM
what's the difference between delete ptr and ptr=0 -dont they accomplish the same Sid C++ 5 07-29-2004 03:42 AM



Advertisments