繁体   English   中英

将函数指针转换为具有更多参数的另一个函数指针

[英]Convert a function pointer to another having more arguments

假设我正在尝试使用一个接受二元函数并使用一些参数调用它的函数:

typedef double (*BinaryFunction)(double a, double b);
typedef double (*UnaryFunction)(double a);

// Can't change this
double ExternalFunction(BinaryFunction binaryFunction)
{
    return binaryFunction(1, 2);
}

现在假设我的代码的用户将为我提供一个一元函数。 我的目标是将其转换为二元函数,以便我可以用它调用ExternalFunction

double MyFunction(UnaryFunction unaryFunction)
{
    BinaryFunction binaryFunction = /* want a function (a, b) -> unaryFunction(a + b) */;
    return ExternalFunction(binaryFunction);
}

我该怎么做呢? 为了清楚起见,我知道如果在编译时知道一元函数,这会很容易,但事实并非如此——它将成为我的函数的参数。 提前致谢。


这是我尝试的总结。 我相信我明白为什么这些不起作用,但我提供它们是为了让你知道我到目前为止一直在想什么。

我不能使用 lambda,因为我必须捕获UnaryFunction ,并且捕获的 lambda 不能转换为函数指针:

double MyFunction(UnaryFunction unaryFunction)
{
    BinaryFunction binaryFunction = [unaryFunction](double a, double b){ return unaryFunction(a + b); };
    return ExternalFunction(binaryFunction);
}

使用std::function吗? 也不能让它工作:

void MyFunction(UnaryFunction unaryFunction)
{
    std::function<double(double, double)> binaryFunctionTemp = [unaryFunction](double a, double b)
    {
        return unaryFunction(a + b);
    };
    BinaryFunction binaryFunction = binaryFunctionTemp.target<double(double, double)>();
    ExternalFunction(binaryFunction);
}

函数对象呢? 不会工作,因为我们需要一个指向成员函数的指针:

class BinaryFromUnary
{
public:
    BinaryFromUnary(UnaryFunction unaryFunction) : unary_(unaryFunction) {};
    double operator()(double a, double b)
    {
        return unary_(a + b);
    }
private:
    UnaryFunction unary_;
};

void MyFunction(UnaryFunction unaryFunction)
{
    BinaryFromUnary functionObject(unaryFunction);
    std::function<double(double, double)> binaryFunction = functionObject;
    ExternalFunction(binaryFunction.target<double(double, double)>());
}

甚至尝试过std::bind (并且可能搞砸了):

struct Converter {
    Converter(UnaryFunction unary) : unary_(unary) {}
    double binary(double a, double b) const { return unary_(a + b); }
    UnaryFunction unary_;
};

void MyFunction(UnaryFunction unaryFunction)
{
    Converter converter(unaryFunction);
    std::function<double(double, double)> binaryFunction = std::bind( &Converter::binary, converter, _1, _2);
    ExternalFunction(binaryFunction.target<double(double, double)>());
}

沿着相同的路线尝试了其他一些事情。 任何想法将不胜感激。

使用外部变量来保存一元函数。

包括关于这是多么不优雅和非线程安全等的标准免责声明,但至少这是符合规定要求的黑客:

#include <iostream>

typedef double (*BinaryFunction)(double a, double b);
typedef double (*UnaryFunction)(double a);

// Can't change this
double ExternalFunction(BinaryFunction binaryFunction) {
  return binaryFunction(1, 2);
}

namespace foo {
UnaryFunction unaryFunction;
}

double MyBinaryFunction(double a, double b) {
  return foo::unaryFunction(a + b);
}

double MyUnaryFunction(double a) {
  return 2 * a;
}

double MyFunction(UnaryFunction unaryFunction) {
  foo::unaryFunction = unaryFunction;
  BinaryFunction binaryFunction = MyBinaryFunction;
  return ExternalFunction(binaryFunction);
}

int main() {
  std::cout << MyFunction(MyUnaryFunction) << std::endl;  // 6
  return 0;
}

我不知道您的确切用例,但这有可能对您有所帮助:

typedef double (*BinaryFunction)(double a, double b);
typedef double (*UnaryFunction)(double a);

// Can't change this
double ExternalFunction(BinaryFunction binaryFunction)
{
    return binaryFunction(1, 2);
}

// If you always know the unary function at compile time:

// Create a wrapper function with the BinaryFunction signature that takes
// a unary function as a NTTP:
template <UnaryFunction unaryFunction>
double wrapper(double a, double b)
{
    return unaryFunction(a + b);
}

// Simply use this wrapper to implement MyFunction as follows:
template <UnaryFunction unaryFunction>
double MyFunction()
{
    return ExternalFunction(wrapper<unaryFunction>);
}

// Using it:

double unary1(double x) { return x * 2; }
double unary2(double x) { return x * 3; }

int main()
{
    std::cout << MyFunction<unary1>() << '\n';
    std::cout << MyFunction<unary2>() << '\n'; 
}

也有一个godbolt链接可以玩它。

与其他答案不同,这不需要全局,但这也只有在您始终在编译时知道您的函数时才有效,而您很可能不知道,所以提前抱歉。 希望它仍然很有趣。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM