如何将成员函数指针传递给模板函数以消除C++代码冗余
代码冗余消除与成员函数指针使用修正
问题核心原因
原代码无法编译的关键错误有两个:
- 成员函数指针传递错误:调用
getNumbersSet时,误传了Base/Derived类的成员函数指针(如&Base::getNumbersSet1),但模板函数实际需要的是T(即SBase/SDerived)类型的成员函数指针。 std::bind用法错误:代码中&T::getNumberFunc是错误写法,getNumberFunc本身已经是T的成员函数指针,无需再取地址。
修正后的实现
1. 修正Base类的模板函数
直接通过成员函数指针调用,代码更简洁高效:
class Base { public: virtual std::vector<int32_t> getNumbersSet1(); virtual std::vector<int32_t> getNumbersSet2(); protected: std::vector<SBase> sVec; private: template<class T> static std::vector<int32_t> getNumbersSet(const std::vector<T>& svec, std::vector<int32_t>(T::* getNumberFunc)() const) { std::vector<int32_t> retval; for (const T& a : svec) { // 直接通过成员函数指针调用目标方法 std::vector<int32_t> tmp = (a.*getNumberFunc)(); retval.insert(retval.end(), tmp.cbegin(), tmp.cend()); } return retval; // 原代码遗漏return语句 } };
若坚持使用std::bind,正确写法如下:
template<class T> static std::vector<int32_t> getNumbersSet(const std::vector<T>& svec, std::vector<int32_t>(T::* getNumberFunc)() const) { std::vector<int32_t> retval; for (const T& a : svec) { auto getNumbersOfT = std::bind(getNumberFunc, std::cref(a)); std::vector<int32_t> tmp = getNumbersOfT(); retval.insert(retval.end(), tmp.cbegin(), tmp.cend()); } return retval; }
2. 修正模板函数的调用代码
传递SBase/SDerived对应的成员函数指针,而非Base/Derived的:
// Base类成员函数实现 std::vector<int32_t> Base::getNumbersSet1() { return getNumbersSet<SBase>(sVec, &SBase::getNumbersSet1); } std::vector<int32_t> Base::getNumbersSet2() { return getNumbersSet<SBase>(sVec, &SBase::getNumbersSet2); } // Derived类成员函数实现 std::vector<int32_t> Derived::getNumbersSet1() { return Base::getNumbersSet<SDerived>(sVec, &SDerived::getNumbersSet1); } std::vector<int32_t> Derived::getNumbersSet2() { return Base::getNumbersSet<SDerived>(sVec, &SDerived::getNumbersSet2); }
额外优化:消除Base与Derived的冗余
Derived类重新定义sVec会隐藏Base的同名成员,可将Base改为模板类进一步简化:
template<typename SType> class BaseTemplate { public: virtual std::vector<int32_t> getNumbersSet1() { return getNumbersSet(sVec, &SType::getNumbersSet1); } virtual std::vector<int32_t> getNumbersSet2() { return getNumbersSet(sVec, &SType::getNumbersSet2); } protected: std::vector<SType> sVec; private: template<class T> static std::vector<int32_t> getNumbersSet(const std::vector<T>& svec, std::vector<int32_t>(T::* getNumberFunc)() const) { std::vector<int32_t> retval; for (const T& a : svec) { std::vector<int32_t> tmp = (a.*getNumberFunc)(); retval.insert(retval.end(), tmp.cbegin(), tmp.cend()); } return retval; } }; // 使用方式 class Base : public BaseTemplate<SBase> {}; class Derived : public BaseTemplate<SDerived> {};
内容的提问来源于stack exchange,提问作者jambodev
相关产品推荐
相关产品推荐

