Thread overview
Initializing a class pointer
Feb 26, 2011
Tyro[a.c.edwards]
Feb 26, 2011
Simen kjaeraas
Feb 26, 2011
Tyro[a.c.edwards]
Feb 26, 2011
Simen kjaeraas
Feb 27, 2011
Tyro[a.c.edwards]
Feb 27, 2011
Tyro[a.c.edwards]
Feb 27, 2011
Bekenn
Feb 28, 2011
Tyro[a.c.edwards]
February 26, 2011
class Class{}

void main()
{
Class myClass;
Class* pClass0 = &myClass;  // OK

Class* pClass1 = new Class; // Error: cannot implicitly convert     [8]
                            // expression (new Class) of type t.Class
                            // to test.Class*
	
Class* pClass2 = &(new Class);
                            // Error: new Class is not an lvalue    [12]
	
Class mClass = &(new Class);// Error: cannot implicitly convert     [14]
	                    // expression (&new Class) of type Class*
	                    // to test.Class
}

C++ uses the process on line [8] above to initialize a class pointer. Obviously it does not work in D. But given the error message at [14], I thought [12] would have been allowed. What is the proper way to convert [8] to D?

Thanks
February 26, 2011
Tyro[a.c.edwards] <nospam@home.com> wrote:

> class Class{}
>
> void main()
> {
> Class myClass;
> Class* pClass0 = &myClass;  // OK
>
> Class* pClass1 = new Class; // Error: cannot implicitly convert     [8]
>                              // expression (new Class) of type t.Class
>                              // to test.Class*
> 	
> Class* pClass2 = &(new Class);
>                              // Error: new Class is not an lvalue    [12]
> 	
> Class mClass = &(new Class);// Error: cannot implicitly convert     [14]
> 	                    // expression (&new Class) of type Class*
> 	                    // to test.Class
> }
>
> C++ uses the process on line [8] above to initialize a class pointer. Obviously it does not work in D. But given the error message at [14], I thought [12] would have been allowed. What is the proper way to convert [8] to D?

Classes in D are already references (like Class& in C++), thus line [8]
would be a pointer to a reference to a class, something which may make
some kind of sense, but is unlikely to be what you want.

Perhaps this question is better answered if you explain why you want a
pointer to a class?


-- 
Simen
February 26, 2011
On 2/27/2011 8:10 AM, Simen kjaeraas wrote:
> Tyro[a.c.edwards] <nospam@home.com> wrote:
>
>> class Class{}
>>
>> void main()
>> {
>> Class myClass;
>> Class* pClass0 = &myClass; // OK
>>
>> Class* pClass1 = new Class; // Error: cannot implicitly convert [8]
>> // expression (new Class) of type t.Class
>> // to test.Class*
>>
>> Class* pClass2 = &(new Class);
>> // Error: new Class is not an lvalue [12]
>>
>> Class mClass = &(new Class);// Error: cannot implicitly convert [14]
>> // expression (&new Class) of type Class*
>> // to test.Class
>> }
>>
>> C++ uses the process on line [8] above to initialize a class pointer.
>> Obviously it does not work in D. But given the error message at [14],
>> I thought [12] would have been allowed. What is the proper way to
>> convert [8] to D?
>
> Classes in D are already references (like Class& in C++), thus line [8]
> would be a pointer to a reference to a class, something which may make
> some kind of sense, but is unlikely to be what you want.
>
> Perhaps this question is better answered if you explain why you want a
> pointer to a class?
>
>

I'm trying to convert some c++ code that defines

T func(par...)
{	
  Controller * pCtrl = WinGetLong<Controller *> (hwnd);
  .
  .
  .
  switch(msg)
  {
  case FirstMatch:
     pCtrl = new Controller (hwnd, reinterpret_cast<CREATESTRUCT *> (lParam));
     break;
  }
}

I'm not sure why I need a pointer to the class, just trying to figure it out.
February 26, 2011
Tyro[a.c.edwards] <nospam@home.com> wrote:

> I'm trying to convert some c++ code that defines
>
> T func(par...)
> {	
>    Controller * pCtrl = WinGetLong<Controller *> (hwnd);
>    .
>    .
>    .
>    switch(msg)
>    {
>    case FirstMatch:
>       pCtrl = new Controller (hwnd, reinterpret_cast<CREATESTRUCT *> (lParam));
>       break;
>    }
> }
>
> I'm not sure why I need a pointer to the class, just trying to figure it out.

Ah. You would not need a pointer to the class in D. Instead, your function
would look something like this:

T funct(par...)
{
    auto pCtrl = WinGetLong!Controller(hwnd);
    ...
    switch(msg)
    {
    case FirstMatch:
        pCtrl = new Controller(hWnd, cast(CREATESTRUCT*)lParam);
        break;
    }
}

C++ classes are in some ways more akin to D structs, in that:

class A {};

void foo(){
    A bar;
}

bar would be allocated on the stack in C++, while in D bar would be a
pointer to a class instance on the heap. (well, it would be null, but
when you set it to something, that something would reside on the heap)

-- 
Simen
February 27, 2011
On 2/27/2011 8:52 AM, Simen kjaeraas wrote:
> Tyro[a.c.edwards] <nospam@home.com> wrote:
>
>> I'm trying to convert some c++ code that defines
>>
>> T func(par...)
>> {
>> Controller * pCtrl = WinGetLong<Controller *> (hwnd);
>> .
>> .
>> .
>> switch(msg)
>> {
>> case FirstMatch:
>> pCtrl = new Controller (hwnd, reinterpret_cast<CREATESTRUCT *> (lParam));
>> break;
>> }
>> }
>>
>> I'm not sure why I need a pointer to the class, just trying to figure
>> it out.
>
> Ah. You would not need a pointer to the class in D. Instead, your function
> would look something like this:
>
> T funct(par...)
> {
> auto pCtrl = WinGetLong!Controller(hwnd);
> ...
> switch(msg)
> {
> case FirstMatch:
> pCtrl = new Controller(hWnd, cast(CREATESTRUCT*)lParam);
> break;
> }
> }
>
> C++ classes are in some ways more akin to D structs, in that:
>
> class A {};
>
> void foo(){
> A bar;
> }
>
> bar would be allocated on the stack in C++, while in D bar would be a
> pointer to a class instance on the heap. (well, it would be null, but
> when you set it to something, that something would reside on the heap)
>

Ok, that's essentially what I have, except that I used Controller pCtrl vice auto. WinGetLong however, is a template that calls GetWindowLongPtrA() and casts it's result (in this case) to Controller.  GetWindowLongPtrA() returns LONG_PTR (aka int) and therefore fails miserably on the cast attempt. On the reverse, there is a WinSetLong that attempts to cast Controller to int for use with SetWindowLongPtrA(). Neither of these functions complain when I use Controller* but I end up with the problem of trying to initialize a pointer with a reference to Controller.
February 27, 2011
On 2/27/2011 9:46 AM, Tyro[a.c.edwards] wrote:
> On 2/27/2011 8:52 AM, Simen kjaeraas wrote:
>> Tyro[a.c.edwards] <nospam@home.com> wrote:
>>
>>> I'm trying to convert some c++ code that defines
>>>
>>> T func(par...)
>>> {
>>> Controller * pCtrl = WinGetLong<Controller *> (hwnd);
>>> .
>>> .
>>> .
>>> switch(msg)
>>> {
>>> case FirstMatch:
>>> pCtrl = new Controller (hwnd, reinterpret_cast<CREATESTRUCT *>
>>> (lParam));
>>> break;
>>> }
>>> }
>>>
>>> I'm not sure why I need a pointer to the class, just trying to figure
>>> it out.
>>
>> Ah. You would not need a pointer to the class in D. Instead, your
>> function
>> would look something like this:
>>
>> T funct(par...)
>> {
>> auto pCtrl = WinGetLong!Controller(hwnd);
>> ...
>> switch(msg)
>> {
>> case FirstMatch:
>> pCtrl = new Controller(hWnd, cast(CREATESTRUCT*)lParam);
>> break;
>> }
>> }
>>
>> C++ classes are in some ways more akin to D structs, in that:
>>
>> class A {};
>>
>> void foo(){
>> A bar;
>> }
>>
>> bar would be allocated on the stack in C++, while in D bar would be a
>> pointer to a class instance on the heap. (well, it would be null, but
>> when you set it to something, that something would reside on the heap)
>>
>
> Ok, that's essentially what I have, except that I used Controller pCtrl
> vice auto. WinGetLong however, is a template that calls
> GetWindowLongPtrA() and casts it's result (in this case) to Controller.
> GetWindowLongPtrA() returns LONG_PTR (aka int) and therefore fails
> miserably on the cast attempt. On the reverse, there is a WinSetLong
> that attempts to cast Controller to int for use with
> SetWindowLongPtrA(). Neither of these functions complain when I use
> Controller* but I end up with the problem of trying to initialize a
> pointer with a reference to Controller.

By the way, in original C++ code WinGetLong and WinSetLong are both using a reinterpret_cast to achieve this monkey magic. To the best of my knowledge, there is no reinterpret_cast facility in D. So the question would be, why would it have been necessary to use reinterpret_cast in the first place and how can similar effect be obtained in D? What was being reinterpreted? Was it the address of the class or the value some private value contained therein?
February 27, 2011
On 2/26/2011 5:33 PM, Tyro[a.c.edwards] wrote:
>> Ok, that's essentially what I have, except that I used Controller pCtrl
>> vice auto. WinGetLong however, is a template that calls
>> GetWindowLongPtrA() and casts it's result (in this case) to Controller.
>> GetWindowLongPtrA() returns LONG_PTR (aka int) and therefore fails
>> miserably on the cast attempt. On the reverse, there is a WinSetLong
>> that attempts to cast Controller to int for use with
>> SetWindowLongPtrA(). Neither of these functions complain when I use
>> Controller* but I end up with the problem of trying to initialize a
>> pointer with a reference to Controller.
>
> By the way, in original C++ code WinGetLong and WinSetLong are both
> using a reinterpret_cast to achieve this monkey magic. To the best of my
> knowledge, there is no reinterpret_cast facility in D. So the question
> would be, why would it have been necessary to use reinterpret_cast in
> the first place and how can similar effect be obtained in D? What was
> being reinterpreted? Was it the address of the class or the value some
> private value contained therein?

What you need here is a double cast; class references can be cast to void*, and from there to LONG_PTR.  The reverse also works:

auto WinGetLong(T)(HWND hwnd)
{
	return cast(T)cast(void*)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
}

void WinSetLong(T)(HWND hwnd, T o)
{
	SetWindowLongPtrA(hwnd, GWLP_USERDATA, cast(LONG_PTR)cast(void*)o;
}
February 27, 2011
On Sat, 26 Feb 2011 19:46:18 -0500, Tyro[a.c.edwards] <nospam@home.com> wrote:

> On 2/27/2011 8:52 AM, Simen kjaeraas wrote:
>> Tyro[a.c.edwards] <nospam@home.com> wrote:
>>
>>> I'm trying to convert some c++ code that defines
>>>
>>> T func(par...)
>>> {
>>> Controller * pCtrl = WinGetLong<Controller *> (hwnd);
>>> .
>>> .
>>> .
>>> switch(msg)
>>> {
>>> case FirstMatch:
>>> pCtrl = new Controller (hwnd, reinterpret_cast<CREATESTRUCT *> (lParam));
>>> break;
>>> }
>>> }
>>>
>>> I'm not sure why I need a pointer to the class, just trying to figure
>>> it out.
>>
>> Ah. You would not need a pointer to the class in D. Instead, your function
>> would look something like this:
>>
>> T funct(par...)
>> {
>> auto pCtrl = WinGetLong!Controller(hwnd);
>> ...
>> switch(msg)
>> {
>> case FirstMatch:
>> pCtrl = new Controller(hWnd, cast(CREATESTRUCT*)lParam);
>> break;
>> }
>> }
>>
>> C++ classes are in some ways more akin to D structs, in that:
>>
>> class A {};
>>
>> void foo(){
>> A bar;
>> }
>>
>> bar would be allocated on the stack in C++, while in D bar would be a
>> pointer to a class instance on the heap. (well, it would be null, but
>> when you set it to something, that something would reside on the heap)
>>
>
> Ok, that's essentially what I have, except that I used Controller pCtrl vice auto. WinGetLong however, is a template that calls GetWindowLongPtrA() and casts it's result (in this case) to Controller.   GetWindowLongPtrA() returns LONG_PTR (aka int) and therefore fails miserably on the cast attempt. On the reverse, there is a WinSetLong that attempts to cast Controller to int for use with SetWindowLongPtrA(). Neither of these functions complain when I use Controller* but I end up with the problem of trying to initialize a pointer with a reference to Controller.

You almost certainly do not want a pointer to a class reference.  A class typically resides on the heap, but the reference typically does not.  Therefore, by using a pointer to a class reference, you run very high risk of escaping stack data, leading to memory corruption.

Looking at the documentation for GetWindowLongPtr, it appears to get data associated with a window.  Likely, this information is the a pointer to the Controller class.

I would recommend doing this:

T WinGetLong(T)(HWND hwnd)
{
   return cast(T)cast(void*)GetWindowLongPtrA(hwnd, ...);
}

and

void WinSetLong(T)(HWND hwnd, T t)
{
   SetWindowLongPtrA(hwnd, ..., cast(LONG_PTR)cast(void*)t);
}

where the ... is the index copied from the C++ code (guessing it's GWLP_USERDATA?).

btw, reinterpret_cast<T>(x) is equivalent to (T)(void *)x;

-Steve
February 28, 2011
On 2/27/2011 10:39 PM, Steven Schveighoffer wrote:
> On Sat, 26 Feb 2011 19:46:18 -0500, Tyro[a.c.edwards] <nospam@home.com>
> wrote:
>
>> On 2/27/2011 8:52 AM, Simen kjaeraas wrote:
>>> Tyro[a.c.edwards] <nospam@home.com> wrote:
>>>
>>>> I'm trying to convert some c++ code that defines
>>>>
>>>> T func(par...)
>>>> {
>>>> Controller * pCtrl = WinGetLong<Controller *> (hwnd);
>>>> .
>>>> .
>>>> .
>>>> switch(msg)
>>>> {
>>>> case FirstMatch:
>>>> pCtrl = new Controller (hwnd, reinterpret_cast<CREATESTRUCT *>
>>>> (lParam));
>>>> break;
>>>> }
>>>> }
>>>>
>>>> I'm not sure why I need a pointer to the class, just trying to figure
>>>> it out.
>>>
>>> Ah. You would not need a pointer to the class in D. Instead, your
>>> function
>>> would look something like this:
>>>
>>> T funct(par...)
>>> {
>>> auto pCtrl = WinGetLong!Controller(hwnd);
>>> ...
>>> switch(msg)
>>> {
>>> case FirstMatch:
>>> pCtrl = new Controller(hWnd, cast(CREATESTRUCT*)lParam);
>>> break;
>>> }
>>> }
>>>
>>> C++ classes are in some ways more akin to D structs, in that:
>>>
>>> class A {};
>>>
>>> void foo(){
>>> A bar;
>>> }
>>>
>>> bar would be allocated on the stack in C++, while in D bar would be a
>>> pointer to a class instance on the heap. (well, it would be null, but
>>> when you set it to something, that something would reside on the heap)
>>>
>>
>> Ok, that's essentially what I have, except that I used Controller
>> pCtrl vice auto. WinGetLong however, is a template that calls
>> GetWindowLongPtrA() and casts it's result (in this case) to
>> Controller. GetWindowLongPtrA() returns LONG_PTR (aka int) and
>> therefore fails miserably on the cast attempt. On the reverse, there
>> is a WinSetLong that attempts to cast Controller to int for use with
>> SetWindowLongPtrA(). Neither of these functions complain when I use
>> Controller* but I end up with the problem of trying to initialize a
>> pointer with a reference to Controller.
>
> You almost certainly do not want a pointer to a class reference. A class
> typically resides on the heap, but the reference typically does not.
> Therefore, by using a pointer to a class reference, you run very high
> risk of escaping stack data, leading to memory corruption.
>
> Looking at the documentation for GetWindowLongPtr, it appears to get
> data associated with a window. Likely, this information is the a pointer
> to the Controller class.
>
> I would recommend doing this:
>
> T WinGetLong(T)(HWND hwnd)
> {
> return cast(T)cast(void*)GetWindowLongPtrA(hwnd, ...);
> }
>
> and
>
> void WinSetLong(T)(HWND hwnd, T t)
> {
> SetWindowLongPtrA(hwnd, ..., cast(LONG_PTR)cast(void*)t);
> }
>
> where the ... is the index copied from the C++ code (guessing it's
> GWLP_USERDATA?).
>
> btw, reinterpret_cast<T>(x) is equivalent to (T)(void *)x;
>
> -Steve

Thank you all (Steve, Bekenn, and Simen) for your assistance on this.