Here is my simplified code: S.h
class SBase {
...
public:
virtual std::vector<int32_t> getNumbersSet1();
virtual std::vector<int32_t> getNumbersSet2();
}
class SDerived : public SBase {
...
public:
virtual std::vector<int32_t> getNumbersSet1() override;
virtual std::vector<int32_t> getNumbersSet2() override;
}
class Base {
public:
virtual std::vector<int32_t> getNumbersSet1();
virtual std::vector<int32_t> getNumbersSet2();
protected:
std::vector<SBase> sVec;
};
class Derived : public Base {
public:
virtual std::vector<int32_t> getNumbersSet1() override;
virtual std::vector<int32_t> getNumbersSet2() override;
protected:
std::vector<SDerived> sVec;
}
Here is my simplified source code: S.cpp
std::vector<int32_t> Base::getNumbersSet1() {
std::vector<int32_t> ret;
for (SBase const& sbase : sVec)
{
std::vector<int32_t> tmp = sbase.getNumbersSet1();
retval.insert(retval.end(), tmp.cbegin(), tmp.cend());
}
return retval;
}
std::vector<int32_t> Base::getNumbersSet2() {
std::vector<int32_t> ret;
for (SBase const& sbase : sVec)
{
std::vector<int32_t> tmp = sbase.getNumbersSet2();
retval.insert(retval.end(), tmp.cbegin(), tmp.cend());
}
return retval;
}
std::vector<int32_t> Derived::getNumbersSet1() {
std::vector<int32_t> ret;
for (SDerived const& sderived : sVec)
{
std::vector<int32_t> tmp = sderived.getNumbersSet1();
retval.insert(retval.end(), tmp.cbegin(), tmp.cend());
}
return retval;
}
std::vector<int32_t> Derived::getNumbersSet2() {
std::vector<int32_t> ret;
for (SDerived const& sderived : sVec)
{
std::vector<int32_t> tmp = sderived.getNumbersSet2();
retval.insert(retval.end(), tmp.cbegin(), tmp.cend());
}
return retval;
}
Now, in order to remove some code duplicates I want to create a template function getNumbersSet() in my Base class, with a view to be able to call it from both getNumbersSet1() and getNumbersSet2() for both Base class and Derived class:
in the source file:
std::vector<int32_t> Base::getNumbersSet1() {
return Base::getNumbersSet<SBase>(sVec, &Base::getNumbersSet1);
}
std::vector<int32_t> Base::getNumbersSet2() {
return Base::getNumbersSet<SBase>(sVec, &Base::getNumbersSet2);
}
std::vector<int32_t> Derived::getNumbersSet1() {
return Base::getNumbersSet<SDerived>(sVec, &Derived::getNumbersSet1);
}
std::vector<int32_t> Derived::getNumbersSet2() {
return Base::getNumbersSet<SDerived>(sVec, &Derived::getNumbersSet2);
}
In order to achieve that This is what I have written the Base::getNumbersSet in the base class:
class Base {
//.... as before
template<class T>
static std::vector<int32_t> getNumbersSet(std::vector<T> const& svec, std::vector<int32_t>(T::* getNumberFunc)() const )) {
std::vector<int32_t> retval;
for (T const& a : svec)
{
auto getNumbersOfT = std::bind(&T::getNumberFunc, a); // problem here
std::vector<int32_t> tmp = getNumbersOfT();
retval.insert(retval.end(), tmp.cbegin(), tmp.cend());
}
}
};
but this won't compile as on the problem line it complains that getNumberFunc is not a member function of type SBase or SDerived.
I have tried to use std::function, std::mem_fn as well but could not get it to work. I hope I have not made too many mistakes when reducing and my code and typing to post here. I appreciate your help.
A couple of problems: you want to be passing &SBase::getNumbersSet1
etc. as your function arguments, not &Base::getNumberSet1
; and your pointer-to-member dereference syntax is wrong. You could change it to std::bind(getNumberFunc, a)
, or just call it like (a.*getNumberFunc)()
.
Here is your code with those changes, compiling: https://godbolt.org/z/o8Kc9oxjG
#include <cstdint>
#include <vector>
class SBase {
public:
virtual std::vector<int32_t> getNumbersSet1() const { return {1, 2}; }
virtual std::vector<int32_t> getNumbersSet2() const { return {2, 3}; }
};
class SDerived : public SBase {
public:
virtual std::vector<int32_t> getNumbersSet1() const override { return {1, 2, 3}; }
virtual std::vector<int32_t> getNumbersSet2() const override { return {2, 3, 4}; }
};
class Base {
public:
virtual std::vector<int32_t> getNumbersSet1();
virtual std::vector<int32_t> getNumbersSet2();
template<class T>
static std::vector<int32_t> getNumbersSet(std::vector<T> const& svec, std::vector<int32_t>(T::* getNumberFunc)() const ) {
std::vector<int32_t> retval;
for (T const& a : svec)
{
std::vector<int32_t> tmp = (a.*getNumberFunc)();
retval.insert(retval.end(), tmp.cbegin(), tmp.cend());
}
return retval;
}
protected:
std::vector<SBase> sVec;
};
class Derived : public Base {
public:
virtual std::vector<int32_t> getNumbersSet1() override;
virtual std::vector<int32_t> getNumbersSet2() override;
protected:
std::vector<SDerived> sVec;
};
std::vector<int32_t> Base::getNumbersSet1() {
return Base::getNumbersSet(sVec, &SBase::getNumbersSet1);
}
std::vector<int32_t> Base::getNumbersSet2() {
return Base::getNumbersSet(sVec, &SBase::getNumbersSet2);
}
std::vector<int32_t> Derived::getNumbersSet1() {
return Base::getNumbersSet(sVec, &SDerived::getNumbersSet1);
}
std::vector<int32_t> Derived::getNumbersSet2() {
return Base::getNumbersSet(sVec, &SDerived::getNumbersSet2);
}
int main() {
Derived hello{};
}