October 7th, 2020

Error C3867: non-standard syntax; use ‘&’ to create a pointer to member: What it means and how to fix it

When you get the Microsoft compiler error message “non-standard syntax; use ‘&’ to create a pointer to member”, what is it trying to say?

It’s telling you that you are accessing an instance member function, but you didn’t finish the job and either take its address or invoke it.

class Class
{
    static void StaticMethod();
    void InstanceMethod();
};
Not valid   Valid
    Class::InstanceMethod()
  ↗︎    
Class::InstanceMethod      
  ↘︎    
    &Class::InstanceMethod

C++ contains a curious discrepancy in how you create pointers to methods, depending on whether the method is instance or static.

For static methods, you can just say its name without any special decoration: Class::StaticMethod. You can put an ampersand in front if you like, but it’s not required.

For instance methods, you cannot say its name without decoration. You must take its address explicitly with the ampersand. The upper right corner of the diagram is illegal.

Syntax Static Instance
Without ampersand  Class::StaticMethod  Class::InstanceMethod
With ampersand &Class::StaticMethod &Class::InstanceMethod

This error message is telling you that it looks like you are trying to create a pointer to an instance member, but you forgot the ampersand. My guess is that the text “non-standard syntax” is an acknowledgement of the fact that very early versions of the Microsoft compiler allowed you to take the address of an instance member without the ampersand, but that is not standard syntax. (I don’t know if the early versions of the compiler actually did permit it, but the wording of the error message suggests it.)

In practice, when you get this error message, you usually aren’t actually trying to create a pointer to a member function. You just forgot to call the method.

Class c;
c.InstanceMethod; // error C3867

Notice that the Microsoft compiler gives you error C3867 in this case, even though there’s clearly no attempt to create a member function pointer. An ampersand here isn’t even legal!

I suspect that this is a case of a more general error case, like “method group not valid here”, and the error text was chosen to be more descriptive of one of the scenarios that would lead to that error, even though it ends up being more confusing for the other scenarios.

But at least now you know what the error is actually trying to tell you, and more importantly, what you probably need to do to fix it. You’re probably trying to call the method. Add the parentheses.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

3 comments

Discussion is closed. Login to edit/delete existing comments.

  • Waleri Todorov

    I always wondered why &MethodName syntax was invalidated in favor of &Class::MethodName.
    After all, when you *call* a method you can use plain MethodName()

  • 紅樓鍮

    For the readers’ convenience, here are versions of the error printed by 4 different compilers.

    Bonus chatter: dontcha think specifying an uninvoked c.InstanceMethod to be synonymous with

    std::bind_front(&Class::InstanceMethod, std::ref(c))

    would be pretty neat?

    • Neil Rashbrook

      I see that clang actually has a readable diagnostic for this case; icc’s diagnostic seems less clear but it at least is suggesting that you forgot to call the function.

      But for the case when you forgot to call a static method, then I like msvc’s diagnostic the best, followed by gcc and then clang (icc doesn’t even warn about this particular error).