3

I was porting some legacy code to VS 2015 when this compiler error halted the build:

error C3867: 'OptDlg::GetFullModel': non-standard syntax; use '&' to create a pointer to member

Going to the corresponding file and line, I saw this:

Manager mgr = GetDocument()->GetManager();
OptDlg dlg;
...
mgr->SetFullModel(dlg.GetFullModel);
if ( dlg.GetFullModel )
    mgr->SetSymm(...

GetFullModeland SetFullModel are the getter/setter pair for a member variable in two different classes:

class Manager {
    ...
    bool GetFullModel() { return m_bFullModel; }
    void SetFullModel(bool bFlag) { m_bFullModel = bFlag; }
    ....
};

class OptDlg {
    ...
    void GetFullModel() { return m_bFullModel; }
    void SetFullModel(bool bValue) { m_bFullModel = bValue; if ( bValue ) m_bInside = 0;}

Yep, something's wrong. Was dlg.GetFullModel supposed to be a pointer to a member function? I thought those use the class name, not an instance. Not to mention what that would mean for execution semantics...

C++ is still relatively new to me, so I tried Google. It had a lot on function pointers, but they all looked different from what I had:

&OptDlg::GetFullModel // Standard-compliant

vs

OptDlg::GetFullModel // The "normal" way to mess up getting a pointer to member, it seems

vs

dlg.GetFullModel // ?

Is dlg.GetFullModel just another way of getting a pointer to member function? If not, what is the "standard C++ version", if there is one? Is this just another one of those VS 6 "extensions"?

awksp
  • 11,764
  • 4
  • 37
  • 44

2 Answers2

5

&OptDlg::GetFullModel // Standard-compliant

If your parameter types were supposed to be taking member functions, that's what you'd use. But they take booleans. It looks like you're just missing parentheses on your function calls, and it should be:

mgr->SetFullModel(dlg.GetFullModel());
if (dlg.GetFullModel())
    mgr->SetSymm(...

Probably someone was ignoring warnings (or didn't have them on) and hence a pointer value (being produced through whatever shady means) was always being interpreted as non-NULL, hence boolean true.

Is this just another one of those VS 6 "extensions"?

It would appear to be the case, although this comment is the only documented evidence I can find it was an intentional/advertised "feature". Don't see any formal announcement of it being added or taken out.

Community
  • 1
  • 1
  • 3
    Emphasis on this: **the code had a severe bug the whole time**! – Lightness Races in Orbit Oct 24 '16 at 18:09
  • @LightnessRacesinOrbit Severity is the product of an equation--involving how bad the failure is, and whether the behavior is ever noticed. So a different takeaway might be *"if this software has been running for years and no one has ever used anything but the full model, maybe that dialog button and option isn't necessary, just delete the code."* – HostileFork says dont trust SE Oct 24 '16 at 18:12
  • Granted. But in the context solely of this function, with a high degree of probability it is 100% broken :) – Lightness Races in Orbit Oct 24 '16 at 18:12
  • Too bad there doesn't seem to be a more authoritative source... At least I know for sure there wasn't some dark corner of C++ that I was unaware of. Thanks! – awksp Oct 24 '16 at 18:47
  • @awksp Visual C++ is several years older than the C++98 standard, so it could have been in there before anyone knew what the right answer was. And they're kind of notorious (historically) for being more interested in keeping customers' existing code running than in standards enforcement. Anyway... [turn up all the warnings](http://stackoverflow.com/a/399865/211160)... check 'em... and then disable the specific ones you're sure you don't care about... – HostileFork says dont trust SE Oct 24 '16 at 19:24
  • I see this error a LOT of the time porting VC6.0 code to VS2013/VS2019 these days. It scares me to know how much VC6.0 code is still running out there on Win32 based embedded systems. – Ross Youngblood Aug 18 '21 at 23:28
4

It strongly looks to me like someone mis-typed dlg.GetFullModel() (which would call the function), not that they were trying to get a member function pointer.

Presumably the legacy compiler let it slide, taking the address of the function without using & and converting the non-null function pointer to bool (with value true) to pass into the set function.

Mark B
  • 95,107
  • 10
  • 109
  • 188