There are a few ways of going about this. One is creating an aggregate type that can forward to the call to the correct comparator.
template <typename T>
struct comp
{
private:
bool desc;
std::greater<T> great;
std::less<T> less;
public:
explicit comp(bool descending = false)
: desc(descending)
{ }
bool operator()(const T& f, const T& g) const
{
return (desc) ? great(f, g) : less(f, g);
}
};
The downside of this is that a comp
object will be at least sizeof(greater + less + bool)
. This may or may not be a problem. Your call to sort would then look something like:
typedef std::wstring str_t;
bool descending = true;
std::sort(vec.begin(), vec.end(), comp<str_t>(descending));
If the decision is always known at compile time, you can play some template tricks:
template <typename T, bool desc>
struct comp;
template <typename T>
struct comp<T, true>
{
private:
std::greater<T> great;
public:
bool operator()(const T& f, const T& g) const
{
return great(f, g);
}
};
template <typename T>
struct comp<T, false>
{
private:
std::less<T> less;
public:
bool operator()(const T& f, const T& g) const
{
return less(f, g);
}
};
This requires descending
to be const
or constexpr
:
constexpr bool descending = false;
std::sort(v.begin(), v.end(), comp<str_t, descending>());
This might be a one step forward, two step back kind of solution. It's quite a bit of code to avoid an if/else
- you'll need to decide if this is worth it at all.
Edit: As @LokiAstari pointed out, you can simplify the above with inheritance:
template <typename T>
struct comp<T, true>
: std::greater<T>
{ }
template <typename T>
struct comp<T, false>
: std::less<T>
{ }
vec::value_type
\$\endgroup\$