简体   繁体   English

我可以在 C++ 中创建通用 function 指针吗?

[英]Can I create generic function pointers in C++?

I've got the following methods:我有以下方法:

Matrix& relu(float threshold, Matrix& M)
Matrix& softmax(Matrix& M)

I'd like to have a function pointer that could receive any of these two methods, is that even possible in C++?我想要一个可以接收这两种方法中的任何一种的 function 指针,这在 C++ 中是否可能? If not are there any elegant workarounds?如果没有,是否有任何优雅的解决方法?

Thanks谢谢

Technically, you can point to both functions with any function pointer.从技术上讲,您可以使用任何 function 指针指向这两个函数。 You'll just need to convert the type explicitly.您只需要显式转换类型。 Of course, you won't be able to call through the pointer if the type does not match.当然,如果类型不匹配,您将无法通过指针调用。

Another option is to store the function pointer in a type erasing wrapper such as std::any or std::variant , which provide a visitation mechanic that may be useful.另一种选择是将 function 指针存储在类型擦除包装器中,例如std::anystd::variant ,它们提供了可能有用的访问机制。

So, you do have ways of pointing to the different functions, but another matter is whether doing so is in any way useful.所以,你确实有办法指向不同的功能,但另一件事是这样做是否有用。

You can use a generic function wrapper std::function :您可以使用通用 function 包装器std::function

Matrix& relu(float threshold, Matrix& M);
Matrix& softmax(Matrix& M);

// Accepts a reference to Matrix, returns a reference to Matrix.
// It probably modifies the input matrix in-place.
using F = std::function<Matrix&(Matrix& M)>; 

int main() {
    F f1{softmax};

    float threshold = 0.1; // threshold gets copied into the lambda capture below.
    F f2{[threshold](Matrix& M) -> Matrix& { return relu(threshold, M); }};

    Matrix m;
    Matrix& m2 = f1(m);
    Matrix& m3 = f2(m);
}

Your activation functions relu and softmax should probably accept a reference to a const vector and return a new vector by value.您的激活函数relusoftmax可能应该接受对 const 向量的引用并按值返回一个新向量。

There is a run time solution, which would bit a bit slower and where you would have to check which type it is有一个运行时解决方案,它会有点慢,你必须检查它是哪种类型

#include <iostream>
#include <functional>
#include <variant>

struct Matrix {
    float test{0};
};

Matrix& relu(float threshold, Matrix& M) {
    M.test = threshold;
    return M;
}
Matrix& softmax(Matrix& M) {
    M.test = 42;
    return M;
}

using matrix_generic_function_pointer_t =
        std::variant<std::function<Matrix&(Matrix&)>, std::function<Matrix& (float, Matrix&)>>;

void use_function(matrix_generic_function_pointer_t function_pointer) {
    Matrix m{}; float something = 1337;

    if (function_pointer.index() == 0) {
        std::cout << "Softmax(): " << std::get<std::function<Matrix&(Matrix&)>>(function_pointer)(m).test;
    } else {
        std::cout << "Relu(): " << std::get<std::function<Matrix& (float, Matrix&)>>(function_pointer)(something,m).test;
    }

}

int main()
{
    matrix_generic_function_pointer_t func1{&relu};
    matrix_generic_function_pointer_t func2{&softmax};

    use_function(func1);

    use_function(func2);

    std::cout << "\n";

}

And there is also a compile time version, which is faster and safer to use, since it will not fail at run time but instead generate a compiler error, but then is a bit more inflexible for you code:还有一个编译时版本,使用起来更快、更安全,因为它不会在运行时失败,而是生成编译器错误,但对你的代码来说有点不灵活:

#include <iostream>
#include <functional>

struct Matrix {
    float test{0};
};

Matrix& relu(float threshold, Matrix& M) {
    M.test = threshold;
    return M;
}
Matrix& softmax(Matrix& M) {
    M.test = 42;
    return M;
}

template <typename F>
void use_function(F&& function) {
    Matrix m{};

    std::cout << function(m).test << "\n";
}

int main()
{
    use_function(std::bind(&relu, 1337, std::placeholders::_1));

    use_function(&softmax);

    std::cout << "\n";
}

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

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