c++language-lawyervirtual-functionsstatic-typingcovariant-return-types

Statically chosen function and virtual function


Recently I've seen this C++ standard paragraph (http://eel.is/c++draft/expr.post#expr.call-5):

If the postfix-expression designates a destructor, the type of the function call expression is void; otherwise, the type of the function call expression is the return type of the statically chosen function (i.e., ignoring the virtual keyword), even if the type of the function actually called is different. This return type shall be an object type, a reference type or cv void.

I don't really understand this part:

the type of the function call expression is the return type of the statically chosen function (i.e., ignoring the virtual keyword), even if the type of the function actually called is different.

  1. What is the statically chosen function here?
  2. How virtual function can be statically chosen? I've always thought that it's chosen at the runtime.
  3. even if the type of the function actually called is different.

How a call expression can actually call function of the different type that was chosen?


Solution

  • First, an example to illustrate.

    struct B { 
      virtual B* f() { return this; }
    };
    
    struct D : B { 
      D* f() override { return this; }
    };
    
    void bar(B*) {}
    void bar(D*) {}
    
    int main() {
      D d;
      B& b = d;
      bar(b.f()); // calls `bar(B*)`
    }
    

    Here, the postfix expression b.f designates a function. It's B::f, and its return type is B*. Even though when overriding f the specified return type is covariant (D*). The fact the actual call is (supposedly) resolved at run-time doesn't change the fact we are choosing the function's identity statically. It's pertinent when there's also overloading involved. The same function name can designate two or more functions, and it's overload resolution that (statically) chooses which overload to call. That overload may be overriden in a derived class, but again its identity is static.