I need some help with working with templates. I have code like this, it's class holding two vectors of std::function object, and a method that pushes some function (bind, lambda, or functor) in one of them:
typedef std::function<int(int)> unFuncPtr;
typedef std::function<int(int, int)> binFuncPtr;
class Operations
{
public:
template <size_t argsCount, class T>
void RegisterOperator(T fn) {
if (argsCount == 1) {
m_unaryOperations.push_back(fn);
}
if (argsCount == 2) {
m_binaryOperations.push_back(fn);
}
}
private:
std::vector<unFuncPtr> m_binaryOperations;
std::vector<binFuncPtr> m_unaryOperations;
I wanted this code to push, for example, lambda with two argements in m_binaryOperations
or lambda with only one argument to m_unaryOperations
calling method RegisterOperator
like this:
Operations operations;
operations.RegisterOperator<1>([](int x) {return x * x; })
operations.RegisterOperator<2>([](int x, int y) {return x y; })
But it gives me a funtion-style-cast error.
As I understand it's because of interpreting class T
in two different ways in one function.
How can I modify the code to call the method with template parameter 1 or 2 for argsCount
, so it will be known what type is class T
and to what vector function from the argument must be pushed?
I tried different ways to solve this problem.
The first one is to overload templates inside the class like this:
template <size_t argsCount, class T>
void RegisterOperator(T fn) {
}
template<>
void RegisterOperator<1>(unFunPtr fn) {
m_unaryOperations.push_back(fn);
}
template<>
void RegisterOperator<2>(binFunPtr fn) {
m_binaryOperations.push_back(fn);
}
But debugging showed me that it won't even go inside overloaded functions with the examples I wrote upper in question.
The second one is to overload templates inside the class like this:
template<class T = unFunPtr>
void RegisterOperator<1>(T fn) {
m_unaryOperations.push_back(fn);
}
template<class T = binFunPtr>
void RegisterOperator<2>(T fn) {
m_binaryOperations.push_back(fn);
}
I thought the default template lets me define only argsCount
in the template when I'm calling the method, but it causes a lot of errors.
Hoping for your help.
CodePudding user response:
First, you have a typo here:
std::vector<unFuncPtr> m_binaryOperations;
std::vector<binFuncPtr> m_unaryOperations;
It should be:
std::vector<unFuncPtr> m_unaryOperations;
std::vector<binFuncPtr> m_binaryOperations;
Second, even then it wouldn't compile, since with "ordinary" if
, both branches needs to be compilable. You can resolve the problem with if constexpr
if you have C 17 available:
void RegisterOperator(T fn) {
if constexpr (argsCount == 1)
m_unaryOperations.push_back(fn);
if constexpr (argsCount == 2)
m_binaryOperations.push_back(fn);
}
Live demo: https://godbolt.org/z/bbqs7Knbd