如何通过指向函数的指针调用具有默认参数的函数,该函数是另一个函数的return?
How to call a function with default parameter through a pointer to function that is the return of another function?
我有函数 Mult, Add, Div, Sub, Mod
接受两个整数和 returns 其参数的结果。函数 Calc
将字符作为 Operator
和 returns 指向函数的指针 returns 一个整数并采用两个整数参数,如 Mult
.
- 像
Mult
这样的函数的第二个参数是default
所以当我调用Calc
时,Calc
returns Mult
的地址或 Add
... 取决于 Calc
的参数值,因此我只能传递一个参数。
但它不适用于指向函数的指针:
int Add(int x, int y = 2) { // y is default
return x + y;
}
int Mult(int x, int y = 2) { // y is default
return x * y;
}
int Div(int x, int y = 2) { // y is default
return y ? x / y : -1;
}
int Sub(int x, int y = 2) { // y is default
return x - y;
}
int Mod(int x, int y = 2) { // y is default
return y ? x % y : -1;
}
using pFn = int(*)(int, int);
pFn Calc(char c) {
switch (c) {
case '+':
return Add;
case '*':
return Mult;
case '/':
return Div;
case '-':
return Sub;
case '%':
return Mod;
}
return Mult;
}
int main(int argc, char* argv[]){
pFn func = Calc('%');
cout << func(7, 4) << endl; // ok
//cout << func(7) << endl; // error: Too few arguments
cout << Mult(4) << endl; // ok. the second argument is default
func = Calc('/'); // ok
cout << func(75, 12) << endl; // ok
std::cout << std::endl;
}
上面如果我用一个参数调用 Mult
它工作正常,因为第二个参数是默认的但是通过指针调用它 func
它失败了。 func 是指向函数的指针,它接受两个整数和 returns 一个 int.
默认参数是一些 C++ 语法糖;当直接调用参数不足的函数时,编译器会插入默认值,就好像调用者已显式传递它一样,因此函数仍会使用完整的参数调用(Mult(4)
被编译成与 Mult(4, 2)
在这种情况下)。
虽然默认值实际上不是函数类型的一部分,因此您不能将默认值用于间接调用;语法糖在那里分解了,因为一旦您通过指针调用,有关默认值的信息就会丢失。
关于 "why not" 我建议你参考 。如果你想以某种方式保持使用默认值的能力,你需要提供比函数指针更多的东西,例如 lamdba 会做:
auto Double() {
return [](int x,int y=2){ return Mult(x,y); };
}
并且通过使用可变 lambda(感谢@Artyer),您甚至不必重复默认值:
#include <iostream>
int Mult(int x, int y = 2) { // y is default
return x * y;
}
auto Double() {
return [](auto... args) { return Mult(args...); };
}
int main(int argc, char* argv[]){
auto func = Double();
std::cout << func(7, 4) << '\n'; // ok
std::cout << func(7) << '\n'; // ok
std::cout << Mult(4) << '\n'; // ok
}
如果您始终将 2
作为默认参数,则可以将您的函数指针包装到一个简单的助手 class 中,如下所示:
using pFn_ = int(*)(int, int);
class pFn
{
pFn_ ptr;
public:
pFn(pFn_ p) : ptr(p) {}
int operator()(int x, int y = 2) const {
return ptr(x,y);
}
};
完整的工作示例:https://godbolt.org/z/5r7tZ8
我有函数 Mult, Add, Div, Sub, Mod
接受两个整数和 returns 其参数的结果。函数 Calc
将字符作为 Operator
和 returns 指向函数的指针 returns 一个整数并采用两个整数参数,如 Mult
.
- 像
Mult
这样的函数的第二个参数是default
所以当我调用Calc
时,Calc
returnsMult
的地址或Add
... 取决于Calc
的参数值,因此我只能传递一个参数。
但它不适用于指向函数的指针:
int Add(int x, int y = 2) { // y is default
return x + y;
}
int Mult(int x, int y = 2) { // y is default
return x * y;
}
int Div(int x, int y = 2) { // y is default
return y ? x / y : -1;
}
int Sub(int x, int y = 2) { // y is default
return x - y;
}
int Mod(int x, int y = 2) { // y is default
return y ? x % y : -1;
}
using pFn = int(*)(int, int);
pFn Calc(char c) {
switch (c) {
case '+':
return Add;
case '*':
return Mult;
case '/':
return Div;
case '-':
return Sub;
case '%':
return Mod;
}
return Mult;
}
int main(int argc, char* argv[]){
pFn func = Calc('%');
cout << func(7, 4) << endl; // ok
//cout << func(7) << endl; // error: Too few arguments
cout << Mult(4) << endl; // ok. the second argument is default
func = Calc('/'); // ok
cout << func(75, 12) << endl; // ok
std::cout << std::endl;
}
上面如果我用一个参数调用 Mult
它工作正常,因为第二个参数是默认的但是通过指针调用它 func
它失败了。 func 是指向函数的指针,它接受两个整数和 returns 一个 int.
默认参数是一些 C++ 语法糖;当直接调用参数不足的函数时,编译器会插入默认值,就好像调用者已显式传递它一样,因此函数仍会使用完整的参数调用(Mult(4)
被编译成与 Mult(4, 2)
在这种情况下)。
虽然默认值实际上不是函数类型的一部分,因此您不能将默认值用于间接调用;语法糖在那里分解了,因为一旦您通过指针调用,有关默认值的信息就会丢失。
关于 "why not" 我建议你参考
auto Double() {
return [](int x,int y=2){ return Mult(x,y); };
}
并且通过使用可变 lambda(感谢@Artyer),您甚至不必重复默认值:
#include <iostream>
int Mult(int x, int y = 2) { // y is default
return x * y;
}
auto Double() {
return [](auto... args) { return Mult(args...); };
}
int main(int argc, char* argv[]){
auto func = Double();
std::cout << func(7, 4) << '\n'; // ok
std::cout << func(7) << '\n'; // ok
std::cout << Mult(4) << '\n'; // ok
}
如果您始终将 2
作为默认参数,则可以将您的函数指针包装到一个简单的助手 class 中,如下所示:
using pFn_ = int(*)(int, int);
class pFn
{
pFn_ ptr;
public:
pFn(pFn_ p) : ptr(p) {}
int operator()(int x, int y = 2) const {
return ptr(x,y);
}
};
完整的工作示例:https://godbolt.org/z/5r7tZ8