Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Function pointer passing compiles in vs2008 but not vs2017

Tags:

c++

mfc

Could someone please tell me why this C++ code compiles successfully in visual studio 2008, but gives an error in visual studio 2017?

class is VStatusSrvr

// array of status response functions created
CArray< void (VStatusSrvr::*)(), void (VStatusSrvr::*&)() > m_fnCreateStsRespArr;


// function call
void VStatusSrvr::CreateLineSegTotalResp()
{
}


// later adding function to array of response functions
m_fnCreateStsRespArr.Add( &VStatusSrvr::CreateLineSegTotalResp);

Error C2664 'INT_PTR CArray::Add(ARG_TYPE)': cannot convert argument 1 from 'void (__thiscall VStatusSrvr::* )(void)' to 'void (__thiscall VStatusSrvr::* &)(void)'

It's from some 20+ year old code that I'm trying to upgrade to vs2017.

What am I missing? Is there a compiler property that needs to be set or cleared that is new to vs2017 (or at least newer than in vs2008)? Or is this just some very old code that no longer compiles? It's a little beyond me.

like image 516
Dan Perry Avatar asked Feb 28 '26 17:02

Dan Perry


1 Answers

(Under assumption that you are talking about MFC's CArray, where the second template parameter ARG_TYPE becomes parameter type for CArray<>::Add member function).

The argument you are passing to Add - &VStatusSrvr::CreateLineSegTotalResp - is not an lvalue. And parameter of Add has type void (VStatusSrvr::*&)(), which is a non-const lvalue reference. In standard C++ you can't bind non-const lvalue references to non-lvalues.

Older versions of Visual Studio allowed this non-standard behavior as an extension, enabled by default. In Visual Studio 2017 this extension still exists, but it is disabled by default. Hence the error.

If you use a const reference (i.e. a reference-to-const) as the second template argument for CArray, it should work

CArray< void (VStatusSrvr::*)(), void (VStatusSrvr::*const &)() > m_fnCreateStsRespArr;
...
m_fnCreateStsRespArr.Add( &VStatusSrvr::CreateLineSegTotalResp);

Anyway, why do you even want to pass a member-function-pointer by reference? Why not just pass it by value and forget about this entire issue?

CArray< void (VStatusSrvr::*)(), void (VStatusSrvr::*)() > m_fnCreateStsRespArr;
like image 142
AnT Avatar answered Mar 02 '26 05:03

AnT



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!