Last updated:2026-10-12
C++ Member Pointers and Type Information¶
::* — probably 99% of people have never used it, or even seen it; feel free to call it out in the comments! This section teaches the syntax from zero, then puts it to work with a real example from a project.
1. What Is ::*¶
C::* is the pointer-to-member syntax in C++; it denotes a pointer to a member of some class C. This syntax is used to point at a class's member variables or member functions. Unlike an ordinary pointer, a member pointer does not point at a concrete memory address of an object; it points at the location of a member within the class and must be used together with an object instance of that class.
1.1 Syntax¶
T C::*is a pointer to a member variable of typeTinside classC.R (C::*)(Args...)is a pointer to a member function of classCwith return typeRand parameter listArgs....
1.2 Pointers to Member Variables¶
A pointer to a member variable points at a member variable of some class, using the form T C::*.
For example: the snippet below defines a member pointer ptr that points at the x member of the class MyClass. obj.*ptr accesses the object's member variable through the member pointer.
struct MyClass {
int x;
double y;
};
int MyClass::*ptr = &MyClass::x;
MyClass obj;
obj.x = 10;
std::cout << "obj.x = " << obj.*ptr << std::endl;
1.3 Pointers to Member Functions¶
A pointer to a member function points at a member function of a class, using the form R (C::*)(Args...).
Example: call the member function via obj.*funcPtr().
3. What Is It Good For?¶
Suppose you have an ORM framework that needs to obtain the field type from a member pointer in order to generate the corresponding column type; you could write:
struct User {
std::string username;
int user_id;
};
// 自动生成数据库列的定义
template <typename T, typename C>
void generate_sql_column(T C::*member_ptr, const std::string& column_name) {
if constexpr (std::is_same_v<T, std::string>) {
std::cout << column_name << " VARCHAR(255)" << std::endl;
} else if constexpr (std::is_integral_v<T>) {
std::cout << column_name << " INT" << std::endl;
}
}
int main() {
// 假设我们想自动为 User 类生成 SQL 表结构
generate_sql_column(&User::username, "username");
generate_sql_column(&User::user_id, "user_id");
return 0;
}
4. A Practical Utility Derived from Real Projects!¶
In real projects, we can use C::* to extract the object type and the member type. How do we implement it?
The answer: templates + C::*
As in the example below, we can extract the corresponding member type and class type through value_type_from_member_pointer and class_type_from_member_pointer — a very convenient utility.
template <typename T, typename C>
struct from_member_pointer_helper<T C::*> {
using value_type = T;
using class_type = C;
};
template <auto Ptr>
struct from_member_pointer : from_member_pointer_helper<typename std::remove_cvref_t<decltype(Ptr)>> {};
template <auto Ptr>
using value_type_from_member_pointer = from_member_pointer<Ptr>::value_type;
template <auto Ptr>
using class_type_from_member_pointer = from_member_pointer<Ptr>::class_type;
Related Topics¶
- C++ Avoiding the Default Constructor | C++那些事
- C++ Class Initializer List Idiom | C++那些事
- C++ Prefer Class Templates over Function Templates | C++那些事
- C++ copy-and-swap Idiom | C++那些事
- C++ Dependency Injection | C++那些事
- C++ enum class Strongly Typed Enums | C++那些事
- C++ Header-Only vs Implementation Separation | C++那些事
- C++ Lazy Evaluation Idiom | C++那些事
- C++ Lookup Table Idiom | C++那些事
- C++ Mixin Idiom | C++那些事