Yes, you can use member function pointers with member functions that have default arguments in C++. However, there are some important considerations and limitations to be aware of.
When creating a pointer to a member function with default arguments, the pointer doesn't carry information about the default arguments. You must provide all arguments when calling through the pointer:
#include <iostream>
class MyClass {
public:
void foo(int a, int b = 10) {
std::cout << "a: " << a << ", b: " << b;
}
};
int main() {
void (MyClass::*ptr)(int, int) = &MyClass::foo;
MyClass obj;
// (obj.*ptr)(5); // Error: too few arguments
(obj.*ptr)(5, 20); // OK
}
a: 5, b: 20
If you have overloaded functions where one version uses default arguments, you need to be explicit about which version you're pointing to:
#include <iostream>
class MyClass {
public:
void bar(int a) {
std::cout << "bar(int): " << a << '\n';
}
void bar(int a, int b = 10) {
std::cout << "bar(int, int): "
<< a << ", " << b << '\n';
}
};
int main() {
void (MyClass::*ptr1)(int) = &MyClass::bar;
void (MyClass::*ptr2)(int, int) = static_cast<
void (MyClass::*)(int, int)>(&MyClass::bar);
MyClass obj;
(obj.*ptr1)(5); // Calls bar(int)
(obj.*ptr2)(5, 20); // Calls bar(int, int)
}
bar(int): 5
bar(int, int): 5, 20
std::function
When using std::function
, you need to specify the full function signature, including all parameters:
#include <functional>
#include <iostream>
class MyClass {
public:
void baz(int a, std::string b = "default") {
std::cout << "a: " << a << ", b: " << b;
}
};
int main() {
std::function<void(
MyClass&, int, std::string
)> func = &MyClass::baz;
MyClass obj;
// func(obj, 5); // Error: too few arguments
func(obj, 5, "custom"); // OK
}
a: 5, b: custom
To leverage default arguments, you can create wrapper functions:
#include <iostream>
class MyClass {
public:
void process(int a, int b = 10, int c = 20) {
std::cout << "a: " << a << ", b: "
<< b << ", c: " << c << '\n';
}
};
void wrapper(MyClass& obj, int a) {
obj.process(a);
}
int main() {
void (*ptr)(MyClass&, int) = wrapper;
MyClass obj;
ptr(obj, 5);
}
a: 5, b: 10, c: 20
We can create a similar solution using a lambda:
#include <functional>
#include <iostream>
class MyClass {
public:
void process(int a, int b = 10, int c = 20) {
std::cout << "a: " << a << ", b: " << b <<
", c: " << c << '\n';
}
};
int main() {
auto bound = [](MyClass& obj, int a,
int b = 10, int c = 20){
obj.process(a, b, c);
};
MyClass obj;
// Uses default for b and c
bound(obj, 5);
// Uses default for c
bound(obj, 5, 15);
// Specifies all arguments
bound(obj, 5, 15, 25);
}
a: 5, b: 10, c: 20
a: 5, b: 15, c: 20
a: 5, b: 15, c: 25
For more flexibility, you can use templates to create generic wrappers:
#include <iostream>
class MyClass {
public:
void process(int a, int b = 10, int c = 20) {
std::cout << "a: " << a
<< ", b: " << b
<< ", c: " << c << '\n';
}
};
template <typename T, typename... Args>
auto makeWrapper(void (T::*func)(Args...)) {
return [func](T& obj, auto... args){
// Capture default values
int b = 10, c = 20;
// Determine how many arguments are passed
if constexpr (sizeof...(args) == 1) {
// Only a is provided
(obj.*func)(args..., b, c);
} else if constexpr (sizeof...(args) == 2) {
// a and b are provided
(obj.*func)(args..., c);
} else {
// All are provided
(obj.*func)(args...);
}
};
}
int main() {
auto wrapper = makeWrapper(&MyClass::process);
MyClass obj;
// Uses default for b and c
wrapper(obj, 5);
// Uses default for c
wrapper(obj, 5, 15);
// Specifies all arguments
wrapper(obj, 5, 15, 25);
}
a: 5, b: 10, c: 20
a: 5, b: 15, c: 20
a: 5, b: 15, c: 25
std::function
, you generally need to provide all arguments explicitly.std::bind
 to leverage default arguments when needed.While member function pointers can be used with functions that have default arguments, it's important to understand the limitations and use appropriate techniques to handle default values when needed.
This often involves creating wrappers or using standard library utilities to achieve the desired behavior.
Answers to questions are automatically generated and may not have been reviewed.
Explore advanced techniques for working with class member functions