如何正确定义可赋值std::plus等C++标准仿函数的变量?
问题描述
我需要声明一个具有确定类型的变量,使其可被赋值为多种C++标准仿函数(例如std::plus、std::multiplies等)。
std::plus的定义如下:
template <class T> struct plus : binary_function <T,T,T> { T operator() (const T& x, const T& y) const {return x+y;} };
我尝试编写了如下代码:
#include <functional> std::binary_function<int, int, int> func = std::plus;
上述代码无法正常编译运行,请问应当如何正确定义符合需求的变量?
错误原因
代码编译失败有两个核心问题:
std::plus是类模板,不是具体的类型,不能直接把模板名作为值赋值,必须指定模板参数完成实例化,比如std::plus<int>{}才是实际可用的仿函数对象。std::binary_function从C11开始被标记为弃用,C17正式从标准库移除。它本身只是一个用于统一类型定义的空基类,没有虚函数,不具备多态存储派生类仿函数的能力,直接值赋值会发生对象切片,完全无法实现多态调用的需求。
正确实现方案
方案1:使用std::function(推荐,C++11及以上版本通用)
std::function是标准库提供的可调用对象类型擦除包装器,可以存储、复制、调用任意匹配签名的可调用对象,包括普通函数、lambda表达式、各类仿函数,完全满足动态切换不同标准仿函数的需求:
#include <functional> #include <iostream> int main() { // 明确指定可调用对象签名:接收两个int参数,返回int值 std::function<int(int, int)> func; // 赋值为std::plus实例 func = std::plus<int>{}; std::cout << func(1, 2) << std::endl; // 输出3 // 可直接重新赋值为其他同签名仿函数 func = std::multiplies<int>{}; std::cout << func(3, 4) << std::endl; // 输出12 return 0; }
方案2:C++98 兼容写法
如果需要兼容没有std::function的C++98老版本环境,可以自行实现简单的多态包装逻辑:
#include <functional> #include <iostream> // 多态二元函数基类 class IntBinaryFunc { public: virtual int operator()(int a, int b) const = 0; virtual ~IntBinaryFunc() {} }; // 具体仿函数包装子类 template <typename F> class FuncWrapper : public IntBinaryFunc { private: F f; public: FuncWrapper(F f) : f(f) {} int operator()(int a, int b) const { return f(a, b); } }; int main() { FuncWrapper<std::plus<int> > plus_wrap(std::plus<int>()); IntBinaryFunc* func = &plus_wrap; std::cout << (*func)(1,2) << std::endl; // 输出3 FuncWrapper<std::multiplies<int> > mul_wrap(std::multiplies<int>()); func = &mul_wrap; std::cout << (*func)(3,4) << std::endl; // 输出12 return 0; }
注意:C++98标准下,模板嵌套的两个右尖括号之间需要加空格,否则会被解析为右移运算符触发编译错误。
内容的提问来源于stack exchange,提问作者razor_chk
相关产品推荐
相关产品推荐

