提问人:Sam Moldenha 提问时间:7/28/2023 最后编辑:JeJoSam Moldenha 更新时间:7/28/2023 访问量:123
有没有办法将函数模板作为另一个函数中的参数传递?
Is there a way to pass a function template, as an argument in another function?
问:
对我来说,描述我所问的最好方式是一个简单的例子。
template<typename T>
void execute_example(T* begin, T* end)
{
T val = 10 * 0.8;
while (begin != end)
{
*begin = val;
val *= 0.8;
++begin;
}
}
using var_t = std::variant<float*, int*, double*>;
// I am just going to assume the type in input is *float to save lines
template<class UnaryOperator>
void my_function(UnaryOperator unary_op, var_t input, size_t size)
{
if (input.index() != 0)
return;
float* begin = std::get<0>(input);
float* end = begin + size;
unary_op<float>(begin, end);
}
int main()
{
float* vals = new float[](10);
my_function(execute_example, vals, 10); // How can I pass execute_example here ??
delete[] vals;
}
我基本上试图弄清楚如何做的是传递一个需要模板作为函数参数的函数。例如,如果我只是将模板参数设置为浮点,而不是模板参数,这将起作用:T
void execute_example(float* begin, float* end)
{
float val = 10 * 0.8;
while (begin != end) {
*begin = val;
val *= 0.8;
++begin;
}
}
using var_t = std::variant<float*, int*, double*>;
// I am just going to assume the type in input is *float to save lines
template<class UnaryOperator>
void my_function(UnaryOperator unary_op, var_t input, size_t size)
{
if (input.index() != 0)
return;
float* begin = std::get<0>(input);
float* end = begin + size;
unary_op<float>(begin, end);
}
int main()
{
float* vals = new float[](10);
my_function(execute_example, vals, 10); // works!!
delete[] vals;
}
即使我更改为以下内容,它仍然不起作用。my_function
template<typename T>
void my_function(std::function<void(T*,T*)> unary_op, var_t input, size_t size)
有没有办法做到这一点?似乎应该有,因为以下内容也有效:
template<class UnaryOperator>
void my_function(UnaryOperator&& unary_op, var_t input, size_t size)
{
if (input.index() != 0)
return;
float* begin = std::get<0>(input);
float* end = begin + size;
std::forward<UnaryOperator>(unary_op)(begin, end);
}
int main()
{
float* vals = new float[10];
my_function([](auto* a, auto* b) {
typedef typename std::remove_pointer<decltype(a)>::type value_t;
value_t val = 10 * 0.8;
while (a != b) {
*a = val;
val *= 0.8;
++a;
}
}, vals, 10);
delete[] vals;
}
这将做同样的事情,我不必指定类型。
答:
4赞
JeJo
7/28/2023
#1
函数模板只是函数集的蓝图,调用方可以在某个时候建立该函数集。在它没有被实例化为聚集类型之前,你不能在那里脱掉任何东西,并将指向它函数的指针传递到任何地方。
此外,即使您也使用 ,问题也保持不变。它所需要的只是一个显式的模板参数。我建议以下,这也不需要.std::function
std::variant
template<class UnaryOperator, typename T>
void my_function(UnaryOperator unary_op, T* input, size_t size) ,
{
unary_op(input, input + size);
}
int main()
{
// use std::vector<float> or smart pointers here (If applicable)
float* vals = new float[10]{};
my_function(&execute_example<float>, vals, 10);
delete[] vals;
}
或者将 作为通用 lambdaexecute_example
inline static constexpr auto execute_example = [](auto* begin, auto* end)
{
// .....
};
template<class UnaryOperator, typename T>
void my_function(UnaryOperator unary_op, T* input, size_t size)
{
unary_op(input, input + size);
}
int main()
{
float* vals = new float[10] {};
// Use std::vector<float> or smart pointers here (if applicable)
my_function(execute_example, vals, 10);
delete[] vals;
}
评论
0赞
Remy Lebeau
7/28/2023
float* vals = new float[10]{}; ... delete[] vals;
可以简化为仅在此示例中。float vals[10]{};
0赞
JeJo
7/28/2023
@RemyLebeau 更好的是使用 or .由于不清楚 OP 的实际用例是什么,我没有在答案中进一步简化这部分。std::array<type, 10>
std::vector<type>
1赞
chrysante
7/28/2023
#2
您可以将函数模板包装在通用 lambda 中。即重写这一行
my_function(execute_example, vals, 10);
对此:
my_function([](auto* begin, auto* end) {
execute_example(begin, end);
}, vals, 10);
调用运算符是一个模板,但 lambda 本身具有具体类型。这就是为什么你可以把它作为参数传递给另一个函数。operator()
评论
while(begin != end)
<
begin
++begin
begin
end
std::for_each
float * input
my_function
//I am just going to assume the type in input is *float to save lines