2

Consider a simple example:

struct FooParent {
   virtual void bar() { }
};

struct Foo: FooParent {
   void bar() { }
};

int main() {
   Foo foo;
   void (Foo::*foo_member)() = &FooParent::bar;
   //(foo.*FooParent::foo_member)();
   foo.FooParent::bar();
}

As you can see one can use scope resolution on the foo object when calling bar member function while there is no way to explicitly declare the scope for member function pointer. I accept that the syntax should be prohibited when using ->* as the operator can be overloaded in sometimes unexpected way, but I cannot understand the reason behind preventing explicit scope resolution when dereferencing with .*.

I am trying to disable virtual dispatch for a member pointer that points to a base class's virtual function.

M.M
  • 138,810
  • 21
  • 208
  • 365
W.F.
  • 13,888
  • 2
  • 34
  • 81

1 Answers1

5

The name of the variable you declared is foo_member, inside your local block scope. It is not a name Foo::foo_member, i.e. the class Foo has no member foo_member. By contrast, the name bar lives in the scope of the class Foo, and also in the scope of the class FooParent.

So the scope resolution mechanism works as expected: it resolves the scope.

[Update:] There is no mechanism to disable virtual dispatch through a member function pointer. You can call a member function of the base subobject like this:

 void (FooParent::*p)() = &FooParent::bar;
 (static_cast<FooParent&>(foo).*p)();

But the call still ends up getting dispatched virtually. The virtuality of the member function is baked into the member function pointer value. The next best thing you can do is to use a lambda:

auto q = [](FooParent & f) { f.FooParent::bar(); };
q(foo);
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • So in other words the reason lays in precedence of the scope operator? – W.F. Sep 21 '16 at 21:44
  • @W.F.: Not at all. The reason is that the purpose of the scope resolution is to resolve scopes, but `foo_member` is already in the current scope, and *not* in the scope of `FooParent`. So if anything, the reason is perhaps your misunderstanding of the concept of a "scope". – Kerrek SB Sep 21 '16 at 21:45
  • Maybe so... But the the concept limits possibility of direct access to virtual member functions using pointers... – W.F. Sep 21 '16 at 21:52
  • And yes you can say that the limit is there for a reason but hey in this case why to give this kind of access from outside overloaded function at all? – W.F. Sep 21 '16 at 21:56
  • 1
    Oh, wait, now I understand what you want to do: You want to perform the direct, static base function call without the virtual dispatch. I didn't get that in your original question. Let me think about that. – Kerrek SB Sep 21 '16 at 22:10
  • 1
    @W.F.: I suppose it's the other way round: The feature to *disable* the virtual call mechanism only exists in the limited form of using the explicit qualification in the class member access expression, but not in the pointer-to-member expressions. (If you think that's a really useful and necessary feature, feel free to propose it as a language extension.) – Kerrek SB Sep 21 '16 at 22:28
  • Actually I already knew about the lambda trick, just wanted to discuss the scope of scope :) I'm not feeling very comfortable when the language limits me when I want to express some basic things... But I guess it's good there are workarounds to get rid of barriers :) – W.F. Sep 21 '16 at 22:33
  • 1
    @W.F.: If you can, please keep track of how often this particular problem comes up over the next, say, three years. If you feel that the language would be significantly enriched if this were a feature, it's entirely feasible to propose this as an extension. We'd mostly want to see good motivating cases where the existing solution is either unbearably worse, or where a core language feature would make code less error prone and easier to understand. – Kerrek SB Sep 21 '16 at 22:36
  • I understand. Thanks for your time and effort! – W.F. Sep 21 '16 at 22:37