-1

I tried to compile the following code.

#include <iostream>

class Base
{
public:
    template <typename T>
    T fun()
    {
        std::cout<<"CALLED!"<<std::endl;
        return T();
    }
};

class Derived : public Base 
{ 

};

template<class T>
T (Derived::*func_ptr)() = &Base::fun;

int main()
{
    Derived d;
    ///how to call?
}

To my surprise, this compiled in both clang and gcc. This gives me the idea that somehow we should be able to call fun by func_ptr. However, I cannot think of what the syntax should be to call the function by this pointer. What is the syntax for it and how is it explained?

Also another thing is, I cannot think of a reason for this to compile. Where is this behavior defined in C++ standard?

Karen Baghdasaryan
  • 2,407
  • 6
  • 24
  • compiles, but undefined behavior, because `fun` is missing a `return` – 463035818_is_not_an_ai Sep 25 '21 at 13:43
  • 2
    _I cannot think of what the syntax should be to call the function by this pointer._ If you don't know how to use pointers-to-members or how to pass arguments to templates, read some C++ intro book. – Language Lawyer Sep 25 '21 at 13:55
  • 4
    The syntax for calling a pointer-to-member is `(o.*f)()`. In this case, the object is `d` and the function pointer is `func_ptr` for some type `T`. There's nothing particularly ambiguous or language-lawyery about this. – Raymond Chen Sep 25 '21 at 13:58
  • Whatever book you're using to learn C++ did you a disservice when it told you how to declare a pointer to a member function, but not how to use it. – Raymond Chen Sep 25 '21 at 14:33

1 Answers1

2

However, I cannot think of what the syntax should be to call the function by this pointer. What is the syntax for it?

(d.*func_ptr<int>)();  // or other template argument

How is it explained? Where is this behavior defined in C++ standard?

func_ptr is a variable template. There are very few rules in the Standard specifically about variable templates, but they are allowed in C++17 and later by [temp.pre] paragraphs 1 and 2.

In your definition

template<class T>
T (Derived::*func_ptr)() = &Base::fun;

the expression &Base::fun is a pointer to overloaded function, as described in [over.over]. When each specialization of the func_ptr template is instantiated, it has a specific pointer-to-function type T (*)() as the target, and the correct template argument for Base::fun<T> can be deduced from that.

To use a variable template, template arguments must be provided. (Template argument deduction can only happen for function templates and class templates.) So func_ptr<int> is an expression of type int (*)(). Then that's combined with the syntax (obj.*mem)(args) for calling a pointer to member function.

aschepler
  • 70,891
  • 9
  • 107
  • 161