简体   繁体   中英

Comparing 2 values using template metaprogramming C++

I want to have a default function as a "Predicate" template in case the user doesn't provide one. So far I've been doing something like:

template<typename T>
struct simple_compare{
    bool operator()(T const& a, T const& b){
        return a > b;
    }
};

template<typename T, typename Predicate=simple_compare<T> >
bool compare(T a, T b, Predicate pred) {
    return pred(a, b);
}

Can this be done using template metaprogramming in C++ instead of having a struct with an overloaded () operator?

You do not need fancy template metaprogramming things. Simply create two versions of the template function. The one without the custom predicate will simply execute the default one.

Something as the following should works:

auto default_pred = [](const auto a, const auto b) {return a > b;};
auto custom_pred  = [](const auto a, const auto b) {return a < b;};


template<typename T, typename Fn >
bool compare2(T a, T b, Fn pred) {
    return pred(a, b);
}

template<typename T >
bool compare2(T a, T b) {
    return default_pred (a, b);
}

int main(){
    cout<<compare2(2, 4)<<endl;
    cout<<compare2(10.2d, 4.5d, custom_pred)<<endl;
   return 0;
}

There is no need for template metaprogramming here. You can simply use overloading like shown in the answer by Davide Spataro to provide a version that doesn't take a predicate and just calls the full version with a default predicate. Or you can just use a default argument for your predicate:

template <typename T, typename Predicate = simple_compare<T>>
bool compare(T a, T b, Predicate pred = {}) {
    return pred(a, b);
}

If you just want a generic functor that invokes the > operator, then you could also just make the operator () a template instead of the functor type itself and let the exact types to compare be deduced from the call:

struct simple_compare {
    template <typename A, typename B>
    bool operator()(A const& a, B const& b) const {
        return a > b;
    }
};

template <typename T, typename Predicate = simple_compare>
bool compare(T a, T b, Predicate pred = {}) {
    return pred(a, b);
}

Also, the standard library already provides standard functors for invoking all sorts of operators. So instead of rolling your own, you could just use std::greater<T> or std::greater<void> in your example. Furthermore, I assume there is no real need to require your arguments to be copyable and of the same type:

template <typename A, typename B, typename Predicate = std::greater<void>>
bool compare(A const& a, B const& b, Predicate pred = {}) {
    return pred(a, b);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM