例如,假设我们有两个函数:
无效总和(int x,int y) { 返回 x+y; } 空减(int x,int y) { 返回 xy; }
有没有一种方法可以创建一个函数来执行求和或减(或各种其他事情),具体取决于您想要使用的(可能通过某种关键字)而无需显式编写单独的函数?
例如,假设我们有两个函数:
无效总和(int x,int y) { 返回 x+y; } 空减(int x,int y) { 返回 xy; }
有没有一种方法可以创建一个函数来执行求和或减(或各种其他事情),具体取决于您想要使用的(可能通过某种关键字)而无需显式编写单独的函数?
有些人用问题下面的评论打败了我,但你走吧!
#include <functional>
#include <iostream>
#include <unordered_map>
std::unordered_map<std::string, std::function<int(int,int)>> operations =
{
{ "plus", std::plus<int>() },
{ "minus", std::minus<int>() }
// etc etc
};
int main(int argc, char** argv)
{
std::cout << operations["plus"](1, 2) << std::endl;
std::cout << operations["minus"](2, 1) << std::endl;
}
我认为该函数实际上比您发布的函数更强大(它不会编译从函数返回值返回void
)。您可以使用函数对象来自定义行为,例如:
#include <functional>
#include <iostream>
using namespace std::placeholders;
template <typename Op>
int operation(int a0, int a1, Op op = Op())
{
return op(a0, a1);
}
int my_f0(int a0, int a2)
{
return 2 * a0 + 3 * a2;
}
int my_f2(int a0, int a2, int f0, int f1)
{
return f0 * a0 + f1 * a2;
}
int main()
{
std::cout << operation<std::plus<int> >(2, 3) << "\n";
std::cout << operation<std::minus<int> >(2, 3) << "\n";
std::cout << operation(2, 3, std::multiplies<int>()) << "\n";
std::cout << operation(2, 3, my_f0) << "\n";
std::cout << operation(2, 3, std::bind(&my_f2, _1, _2, 2, 3)) << "\n";
}
自定义函数是operation()
. 其他代码只是为了展示它是如何被定制的。标准库算法到处都使用这种方法。
是不想编写单独的函数,还是想从调用站点调用一件事?如果你不介意多写一点,你可以使用操作符对象:
class Add {
public:
int operator(int a, int b) {
return a+b:
}
};
class Mul {
public:
int operator(int a, int b) {
return a*b:
}
};
template <class Op>
int doMyStuff(Op op, int a, int b) {
return op(a,b);
}
// and you can call it like this:
doMyStuff(Add(),2,4);
当您实现某些不依赖于特定运算符而仅依赖于运算符的某些属性的转换时,此模式特别有用。例如,您可以实现一个数组求和器,它要么对数组的所有元素求和,要么计算数组中所有元素的乘积:循环保持不变,只是运算符发生了变化。
template <class Op>
int summator(Op op, int* arr, int size) {
int v = arr[0];
for (int i=1; i<size; ++i) {
v = op(v,arr[i]);
}
return v;
}
...
summator(Add(),myarray,10); //sum all elements
summator(Mul(),myarray,10); //product of all elements
如果你不相信宏是从地狱来的邪恶,你可以这样做:
#define DEFINE_OPERATION(maName, maOp) \
inline int maName (int a, int b) { return a maOp b; }
DEFINE_OPERATION(add, +)
DEFINE_OPERATION(sub, -)
#undef DEFINE_OPERATION
甚至:
#include <boost/preprocessor.hpp>
#define OPERATIONS ((add, +))((sub, -))
#define DEFINE_OPERATION(maR, maData, maElem) \
inline int BOOST_PP_TUPLE_ELEM(2, 0, maElem) (int a, int b) { return a BOOST_PP_TUPLE_ELEM(2, 1, maEleme) b; }
BOOST_PP_SEQ_FOR_EACH(OPERATIONS, unused_, DEFINE_OPERATION)
#undef DEFINE_OPERATION
#include <iostream>
#include <functional>
using namespace std;
template<template<class> class OP, class T>
T do_op(T a, T b) {
return OP<T>()(a,b);
}
int main () {
cout << do_op<plus> (3,2) << endl;
cout << do_op<minus> (3,2) << endl;
cout << do_op<multiplies> (3,2) << endl;
cout << do_op<divides> (3,2) << endl;
}