英文:
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;
}
即使我将 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;
}
这将执行相同的操作,而且我不必指定一个类型。
英文:
The best way for me to describe what I am asking is a simple example.
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;
}
What I am basically trying to figure out how to do is pass a function that needs a template as a function argument. For example, this would work, if instead of a template argument I just set T
to float:
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;
}
Even if I changed my_function
to the following, it still wouldn't work.
template<typename T>
void my_function(std::function<void(T*,T*)> unary_op, var_t input, size_t size)
Is there a way to do this? It seems like there should be because the following is also valid:
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;
}
Which would do the same thing, and I would not have to specify a type.
答案1
得分: 4
函数模板只是一组函数的蓝图,调用者可以在某个时刻实例化它。除非它已经被实例化为具体的类型,否则无法访问其中的任何内容并将指针传递给它的函数。
此外,即使使用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()
{
// 在这里使用std::vector<float>或智能指针(如果适用)
float* vals = new float[10]{};
my_function(&execute_example<float>, vals, 10);
delete[] vals;
}
或将execute_example
定义为通用lambda函数:
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]{};
// 在这里使用std::vector<float>或智能指针(如果适用)
my_function(execute_example, vals, 10);
delete[] vals;
}
英文:
A function template is just a blueprint to the set of function, which caller may institute at some point. Until it hasn't been instantiated with congregate type, there you can not undress anything and pass the pointer to the function of it, to anywhere.
Additionally, the issue stays the same, even when you use the std::function
as well. All it needs is an explicit template argument. I suggest the following, which also doesn't required the 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;
}
Or make the execute_example
as a generic lambda
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;
}
答案2
得分: 1
你可以将函数模板包装在一个通用lambda中。也就是说,将这行代码重写为:
my_function([](auto* begin, auto* end) {
execute_example(begin, end);
}, vals, 10);
调用运算符 operator()
是一个模板,但 lambda 本身具有具体的类型。这就是为什么你可以将它作为参数传递给另一个函数的原因。
英文:
You can wrap the function template in a generic lambda. I.e. rewrite this line
my_function(execute_example, vals, 10);
to this:
my_function([](auto* begin, auto* end) {
execute_example(begin, end);
}, vals, 10);
The call operator operator()
is a template, but the lambda itself has a concrete type. Thats why you can pass it as an argument to another function.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论