When defining a class, this class can be used as if it were declared forward. Since ptr_to_member uses pointers only to T , until you create one of its methods, it does not complain. Try adding a T element instead of a pointer, and you will see that it does not work. An intuitive way to make sure you don’t need to know that T use a pointer T , only that T is a type. Pointers behave the same, no matter what they point to, until you spot them.
template <class T> struct ptr_to_member { using ptr_type = void (T::*)(); ptr_type m_ptr; ptr_to_member() : m_ptr(&T::f) {} auto get_ptr() const { return m_ptr; } T member;
See this answer for more information on when you can and cannot use forward declared types.
source share