我可以在 C++ 中创建通用函数指针吗?
Can I create generic function pointers in C++?
我有以下方法:
Matrix& relu(float threshold, Matrix& M)
Matrix& softmax(Matrix& M)
我想要一个可以接收这两种方法中的任何一种的函数指针,这在 C++ 中是否可行?
如果没有,是否有任何优雅的解决方法?
谢谢
从技术上讲,您可以使用任何函数指针指向这两个函数。您只需要显式转换类型。当然,如果类型不匹配,你将无法通过指针调用。
另一种选择是将函数指针存储在类型擦除包装器中,例如 std::any
或 std::variant
,这提供了可能有用的访问机制。
因此,您确实有指向不同函数的方法,但另一个问题是这样做是否有任何用处。
您可以使用通用函数包装器 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);
}
您的激活函数 relu
和 softmax
可能应该接受对 const 向量的引用和 return 新向量的值。
有一个 运行 时间解决方案,它会有点慢,您必须在哪里检查它是哪种类型
#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";
}
还有一个编译时版本,使用起来更快更安全,因为它不会在 运行 时失败,而是产生编译错误,但对你来说有点不灵活代码:
#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";
}
我有以下方法:
Matrix& relu(float threshold, Matrix& M)
Matrix& softmax(Matrix& M)
我想要一个可以接收这两种方法中的任何一种的函数指针,这在 C++ 中是否可行? 如果没有,是否有任何优雅的解决方法?
谢谢
从技术上讲,您可以使用任何函数指针指向这两个函数。您只需要显式转换类型。当然,如果类型不匹配,你将无法通过指针调用。
另一种选择是将函数指针存储在类型擦除包装器中,例如 std::any
或 std::variant
,这提供了可能有用的访问机制。
因此,您确实有指向不同函数的方法,但另一个问题是这样做是否有任何用处。
您可以使用通用函数包装器 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);
}
您的激活函数 relu
和 softmax
可能应该接受对 const 向量的引用和 return 新向量的值。
有一个 运行 时间解决方案,它会有点慢,您必须在哪里检查它是哪种类型
#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";
}
还有一个编译时版本,使用起来更快更安全,因为它不会在 运行 时失败,而是产生编译错误,但对你来说有点不灵活代码:
#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";
}