Home > Enterprise >  How to create a template that can use different arguments from the same base class
How to create a template that can use different arguments from the same base class

Time:10-23

I'm trying to create a Threshold template class that allows me to compare numeric values against a threshold value. I want to easily change the comparison function to use greater_equal or less_equal so I create the following template:

template<typename T, typename comp_func = std::greater_equal<T>, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
class Threshold
{
public:
    Threshold(T threasholdValue) : _thresholdValue(threasholdValue) {}
    ~Threshold() = default;

    bool isExceeded(T value) const
    {
        return comp_func{}(value, _thresholdValue);
    }

private:
    T _thresholdValue;
};

I want to be able to pass instances of this class to a function that accepts the Threshold:

template<typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
void foo(Threshold<T>& threshold)
{
. . .
}

This works fine as long as I use the default comparison function (std::greater_equal) but when I try to create a Threashold with "std::less_equal", this becomes a different type and I cannot pass it into foo:

Threshold<int32_t> greaterEqThreshold(5);
Threshold<int32_t, std::less_equal<int32_t>> lessEqThreshold(10);

foo(greaterEqThreshold);
foo(lessEqThreshold);  <--- Compile Error!

I understand why this is happening but I can't figure out how to solve the problem, other by creating a pure virtual class and having Threshold inherit from it and then using reference to that class. However, this solutions seems a little long winded for what I want do do.

Is there a way to make this work? Is there a better way to do this?

Edit

std::less_equal and std::greater_equal both inherit from std::binary_function (hence the title of my question), so I tried this:

template<typename T, typename _Compare_func = std::less_equal<T>, typename std::enable_if<std::is_arithmetic<T>::value || std::is_same<std::binary_function<T, T, bool>, _Compare_func>::value>::type* = nullptr>
class Threshold
{
public:
...
};

but that didn't seem to make a difference.

CodePudding user response:

You specifically declared foo as a function that only takes a Threshold<T>, i.e. an instance of a template where the comparator is the default. Just include both template arguments in your definition:

template<typename T, typename comp_func, 
    typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
void foo(Threshold<T, comp_func>& threshold)
{
  // . . .
}
  • Related