Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
函数作为模板参数传递 我正在寻找有关将C++模板函数作为参数传递的规则。 这是由C++支持的,如这里的例子所示: #include <iostream> void add1(int &v) { v+=1; } void add2(int &v) { v+=2; } template <void (*T)(int &)> void doOperation() { int temp=0; T(temp); std::cout << "Result is " << temp << std::endl; } int main() { doOperation<add1>(); doOperation<add2>(); } #包括 无效地址1(内部和外部) { v+=1; } 无效地址2(内部和外部) { v+=2; } 模板 无效操作() { 内部温度=0; T(温度); std::cout_C++_Templates_Code Generation_Functor - Fatal编程技术网

函数作为模板参数传递 我正在寻找有关将C++模板函数作为参数传递的规则。 这是由C++支持的,如这里的例子所示: #include <iostream> void add1(int &v) { v+=1; } void add2(int &v) { v+=2; } template <void (*T)(int &)> void doOperation() { int temp=0; T(temp); std::cout << "Result is " << temp << std::endl; } int main() { doOperation<add1>(); doOperation<add2>(); } #包括 无效地址1(内部和外部) { v+=1; } 无效地址2(内部和外部) { v+=2; } 模板 无效操作() { 内部温度=0; T(温度); std::cout

函数作为模板参数传递 我正在寻找有关将C++模板函数作为参数传递的规则。 这是由C++支持的,如这里的例子所示: #include <iostream> void add1(int &v) { v+=1; } void add2(int &v) { v+=2; } template <void (*T)(int &)> void doOperation() { int temp=0; T(temp); std::cout << "Result is " << temp << std::endl; } int main() { doOperation<add1>(); doOperation<add2>(); } #包括 无效地址1(内部和外部) { v+=1; } 无效地址2(内部和外部) { v+=2; } 模板 无效操作() { 内部温度=0; T(温度); std::cout,c++,templates,code-generation,functor,C++,Templates,Code Generation,Functor,是的,它是有效的 至于如何使其与函子一起工作,通常的解决方案是这样的: template <typename F> void doOperation(F f) { int temp=0; f(temp); std::cout << "Result is " << temp << std::endl; } 问题是,如果编译器内联调用add2,会变得很棘手,因为编译器只知道函数指针类型void(*)(int&)正在传递给doOperat

是的,它是有效的

至于如何使其与函子一起工作,通常的解决方案是这样的:

template <typename F>
void doOperation(F f)
{
  int temp=0;
  f(temp);
  std::cout << "Result is " << temp << std::endl;
}


问题是,如果编译器内联调用
add2
,会变得很棘手,因为编译器只知道函数指针类型
void(*)(int&)
正在传递给
doOperation
。(但是
add3
,作为一个functor,可以很容易地内联。在这里,编译器知道类型为
add3
的对象被传递给函数,这意味着要调用的函数是
add3::operator()
,而不仅仅是一些未知的函数指针。)

您的functor示例不起作用的原因是您需要一个实例来调用模板中的
操作符()

template <void (*T)(int &)>
void doOperation()

还有一些次要的性能考虑。此新版本可能会降低函数指针参数的效率,因为特定函数指针仅在运行时解除保护并调用,而函数指针模板可以优化(可能是函数调用内联)基于所使用的特定函数指针。函数对象通常可以通过类型化模板非常有效地扩展,尽管作为特定的
运算符()
完全由函数对象的类型决定。

编辑:将运算符作为引用传递不起作用。为简单起见,请将其理解为函数指针。只发送指针,而不是引用。 我想你是想写这样的东西

struct Square
{
    double operator()(double number) { return number * number; }
};

template <class Function>
double integrate(Function f, double a, double b, unsigned int intervals)
{
    double delta = (b - a) / intervals, sum = 0.0;

    while(a < b)
    {
        sum += f(a) * delta;
        a += delta;
    }

    return sum;
}
struct Square
{
双运算符()(双数字){返回数字*数字;}
};
模板
双积分(函数f,双a,双b,无符号整数区间)
{
双增量=(b-a)/区间,总和=0.0;
while(a


std::cout模板参数可以通过类型(typename T)或值(int X)进行参数化

模板的一个“传统”C++方式是使用一个函子,即代码在一个对象中,对象因此给出代码唯一的类型。 在使用传统函数时,此技术不起作用,因为类型的更改并不表示特定函数,而是只指定许多可能函数的签名。因此:

template<typename OP>
int do_op(int a, int b, OP op)
{
  return op(a,b);
}
int add(int a, int b) { return a + b; }
...

int c = do_op(4,5,add);
仍然是合法的,显然这不是内联的。要获得完全内联,我们需要按值模板,因此该函数在模板中完全可用

typedef int(*binary_int_op)(int, int); // signature for all valid template params
template<binary_int_op op>
int do_op(int a, int b)
{
 return op(a,b);
}
int add(int a, int b) { return a + b; }
...
int c = do_op<add>(4,5);
template <typename T> struct BinOp
{
    typedef T(*binary_T_op )(T, T); // signature for all valid template params
    template<binary_T_op op>
    T do_op(T a, T b)
    {
       return op(a,b);
    }
};


double mulDouble(double a, double b)
{
    return a * b;
}


BinOp<double> doubleBinOp;

double res = doubleBinOp.do_op<&mulDouble>(4, 5);

相比之下,我们的By-value案例要求函数参数完全匹配。

函数指针可以作为模板参数传递,并且 但在模板中,它们被声明并用作函数,而不是函数指针。在模板实例化时,传递函数的地址而不仅仅是名称

例如:

int i;


void add1(int& i) { i += 1; }

template<void op(int&)>
void do_op_fn_ptr_tpl(int& i) { op(i); }

i = 0;
do_op_fn_ptr_tpl<&add1>(i);

老实说,我真的希望它不会编译,但它在gcc-4.8和Visual Studio 2013中对我起到了作用。

带来了额外的要求,参数/返回类型也应该有所不同。 在Ben Supnik之后,这将适用于某些类型的T

typedef T(*binary_T_op)(T, T);
而不是

typedef int(*binary_int_op)(int, int);
这里的解决方案是将函数类型定义和函数模板放入周围的结构模板中

typedef int(*binary_int_op)(int, int); // signature for all valid template params
template<binary_int_op op>
int do_op(int a, int b)
{
 return op(a,b);
}
int add(int a, int b) { return a + b; }
...
int c = do_op<add>(4,5);
template <typename T> struct BinOp
{
    typedef T(*binary_T_op )(T, T); // signature for all valid template params
    template<binary_T_op op>
    T do_op(T a, T b)
    {
       return op(a,b);
    }
};


double mulDouble(double a, double b)
{
    return a * b;
}


BinOp<double> doubleBinOp;

double res = doubleBinOp.do_op<&mulDouble>(4, 5);
模板结构BinOp
{
typedef T(*binary_T_op)(T,T);//所有有效模板参数的签名
模板
T do_op(T a,T b)
{
返回op(a,b);
}
};
双倍(双倍a,双倍b)
{
返回a*b;
}
双联双联;
double res=doubleBinOp.do_op(4,5);
或者,BinOp可以是一个带有静态方法模板do_op(…)的类,然后称为

double res = BinOp<double>::do_op<&mulDouble>(4, 5);
double res=BinOp::do_op(4,5);

现在有一个有趣的问题。当传递函数名时,它不像是包含函数指针。它是一个显式函数,在编译时给出。因此编译器确切地知道它在编译时得到了什么。比起函数指针,使用函子有一个优势。函子可以在类内实例化,然后因此为编译器提供了更多的优化操作(如内联)。编译器将很难优化对函数指针的调用。当在模板参数中使用该函数时,它会“衰减”为指向传递函数的指针。这对于数组作为参数传递时如何衰减为指针是很有帮助的。当然,指针值在编译时是已知的,并且必须指向函数使用外部链接进行初始化,以便编译器可以将此信息用于优化目的。快进到几年后,在C++11中使用函数作为模板参数的情况有了很大改善。您不再像函子类那样使用Javaisms,可以直接使用静态内联函数作为模板参数。仍然是f与20世纪70年代的Lisp宏相比,C++11无疑取得了长足的进步。既然C++11将函数作为右值引用(
template void doOperation(F&&F){/**/}
)不是更好吗,例如bind可以传递一个bind表达式,而不是绑定它?函数作为模板参数的好处是什么?返回类型不会用作模板类型吗?相关:没有捕获的lambda可以衰减为函数指针,您可以在C++17中将其作为模板参数传递。Clang编译它是正确的,但当前的gcc(8.2)有一个bug,即使使用
-std=gnu++17
,也会错误地拒绝它,因为它“没有链接”。请参阅此处对观察到的
int c=
convert a and b from int to float.
call the function ptr op with float a and float b.
convert the result back to int and return it.
int i;


void add1(int& i) { i += 1; }

template<void op(int&)>
void do_op_fn_ptr_tpl(int& i) { op(i); }

i = 0;
do_op_fn_ptr_tpl<&add1>(i);
struct add2_t {
  void operator()(int& i) { i += 2; }
};

template<typename op>
void do_op_fntr_tpl(int& i) {
  op o;
  o(i);
}

i = 0;
do_op_fntr_tpl<add2_t>(i);
template<typename op>
void do_op_fntr_arg(int& i, op o) { o(i); }

i = 0;
add2_t add2;

// This has the advantage of looking identical whether 
// you pass a functor or a free function:
do_op_fntr_arg(i, add1);
do_op_fntr_arg(i, add2);
// non-type (function pointer) template parameter
template<void op(int&)>
void do_op(int& i) { op(i); }

// type (functor class) template parameter
template<typename op>
void do_op(int& i) {
  op o; 
  o(i); 
}

i = 0;
do_op<&add1>(i); // still need address-of operator in the function pointer case.
do_op<add2_t>(i);
typedef T(*binary_T_op)(T, T);
typedef int(*binary_int_op)(int, int);
template <typename T> struct BinOp
{
    typedef T(*binary_T_op )(T, T); // signature for all valid template params
    template<binary_T_op op>
    T do_op(T a, T b)
    {
       return op(a,b);
    }
};


double mulDouble(double a, double b)
{
    return a * b;
}


BinOp<double> doubleBinOp;

double res = doubleBinOp.do_op<&mulDouble>(4, 5);
double res = BinOp<double>::do_op<&mulDouble>(4, 5);