对我来说描述我所问问题的最好方法是一个简单的例子。
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);
delete[] vals;
}
我基本上想弄清楚如何做是传递一个需要模板作为函数参数的函数。例如,如果我不使用模板参数,而是将
T
设置为 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);
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;
}
这会做同样的事情,而且我不必指定类型。
函数模板只是函数集的蓝图,调用者可能会在某个时刻调用它。在它没有被聚合类型实例化之前,你不能脱掉任何东西并将指针传递给它的函数,到任何地方。
此外,即使您也使用
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;
}
或者将
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] {};
// Use std::vector<float> or smart pointers here (if applicable)
my_function(execute_example, vals, 10);
delete[] vals;
}