In a template function a std::vector shall get sorted. T can be a simple type or a std::pair e.g.,
std::vector<double> or
std::vector<std::pair<int,Something> >
When T is a pair then only the first element shall be compared. How can I implement the comparator for the two cases?
I have tried:
template<typename T>
inline bool smaller(const T& a,const T& b)
{
return a<b;
}
template<typename T,typename S>
inline bool smaller(
const std::pair<T,S>& a,
const std::pair<T,S>& b
)
{
return a.first<b.first;
}
template<typename T> inline void function(std::vector<T >& vVec)
{
...bla...
sort(vVec.begin(),vVec.end(),smaller<T>);
...bla...
}
but it does not work this way. I have also tried specialization but I do not find the right syntax to specialize the smaller() function.
You could just wrap it in a lambda:
std::sort(vVec.begin(),vVec.end(), [](const auto& a, const auto& b) { return smaller(a, b); });
One easy work around is to make both of your smaller functions opeator()'s of a smaller struct. Using
struct smaller
{
template<typename T>
bool operator()(const T& a,const T& b)
{
return a < b;
}
template<typename T, typename S>
bool operator() (const std::pair<T, S>& a, const std::pair<T, S>& b)
{
return a.first < b.first;
}
};
allows you to just pass a smaller to sort like
template<typename T> inline void function(std::vector<T >& vVec)
{
sort(vVec.begin(),vVec.end(),smaller{});
}
and in sort overload resolution will kick in on the two operator() smaller has and for any std::vector<std::pair>, the std::pair overload will be called.
Related
I have encountered this greater<pair<int,int>> in many codes.
For example, in the initialisation of the priority queue [code below]
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;
I tried a lot of googling but still couldn't find the best answer.
This is the std::greater type.
This is a function object type that does comparisons using the > operator. A rough implementation looks like this:
template<typename T>
struct greater {
constexpr auto operator()(T const& a, T const& b) const -> bool {
return a > b; // greater operator
}
};
In your example, this is being used to order the std::pairs in the priority_queue from "smallest" to "largest" using std::pair's operator >.
The std::greater is a template function object defined as:
template<typename T> struct greater {
constexpr bool operator()(T const& a, T const& b) const {
return a > b; // greater operator
}
};
Now, the '>' operator is defined for std::pair as -
template <class T1, class T2>
bool operator> (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs) { return rhs<lhs; }
Now, the '<' operator is defined as-
template <class T1, class T2>
bool operator< (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
{ return lhs.first<rhs.first || (!(rhs.first<lhs.first) && lhs.second<rhs.second); }
So, effectively, the function greater<pair<int, int>> works as-
template<typename T> struct greater {
constexpr bool operator()(T const& a, T const& b) const {
return a.first>b.first || ( (a.first<b.first) && (a.second>b.second));
}
};
That is, greater<pair<int, int>>(a, b) returns true if and only if the 'first' parameter of a is greater than b or if 'first' parameters are equal then 'second' parameter of a is greater than b.
This is a strict weak ordering.
For example, if I have the following variant and a static_visitor:
typedef boost::variant<long, int, float, double> DataType;
And I'd like this to work:
DataType x(1.2);
DataType y(100);
std::cout<<boost::apply_visitor(Multiply(), x, y)<<std::endl; // should return 120
with a visitor like this:
struct Multiply : public boost::static_visitor<DataType>
{
template<typename T, typename U>
DataType operator()(const T& a, const U& b) const
{
// what to do here??
}
template<typename T>
DataType operator()(const T& a, const T& b) const
{
return a * b;
}
};
How I can do this without having to list all the possible combinations of types in the Multiply visitor?
My advice: Don't special-case on same type, but on multiplyability:
struct Multiply : public boost::static_visitor<DataType> {
template<typename T, typename U>
static auto operator()(const T& a, const U& b) const
-> decltype(DataType(a*b)){
return a*b;
}
template<typename... Ts>
static DataType operator()(const Ts... params) const {
throw std::invalid_argument("can't multiply");
}
};
Changes:
No special-casing of any combination which works.
Throwing an exception on any combination which does not.
Now static.
Uses expression-SFINAE to decide.
Still, it won't return 120 for your example, because binary floating-point cannot represent 1.2 exactly.
I'm working in C++98 and I want to bind std::max. But I need a functor object to use with std::bind1st.
I've tried just using std::pointer_to_binary_function but the problem seems to be that I can't make a functor out of std::max: https://stackoverflow.com/a/12350574/2642059
I've also tried std::ptr_fun but I get a similar error.
Because of the issue in this answer, you can't write a true wrapper functor for max because you can't make any of the types const T&. The best you can do is:
template <typename T>
struct Max
: std::binary_function<T, T, T>
{
T operator()(T a, T b) const
{
return std::max(a, b);
}
};
std::bind1st(Max<int>(), 1)(2) // will be 2
But that sucks, since you now have to copy everything (although if you're just using ints, this is totally fine). Best would probably be to just avoid bind1st altogether:
template <typename T>
struct Max1st
{
Max1st(const T& v) : first(v) { }
const T& operator()(const T& second) const {
return std::max(first, second);
}
const T& first;
};
Context: C++03 only + the use of boost is authorized
I'd like to raise the same question as in
How to negate a predicate function using operator ! in C++?
... but with an overloaded boolean predicate, that is:
struct MyPredicate
{
bool operator()(T1) const;
bool operator()(T2) const;
};
Clearly, MyPredicate cannot be derived from std::unary_function as it is impossible to define a single argument_type.
The aim is to use MyPredicate as argument to range adaptors, with a readable syntax like this:
using boost::for_each;
using boost::adaptors::filtered;
list<T1> list1;
list<T2> list2;
for_each(list1 | filtered(!MyPredicate()), doThis);
for_each(list2 | filtered(!MyPredicate()), doThat);
Of course, any solution involving explicit disambiguation is of no interest here.
Thank you in advance.
[ACCEPTED SOLUTION]
I'm using a slightly modified version of Angew's solution:
template <class Predicate>
struct Not
{
Predicate pred;
Not(Predicate pred) : pred(pred) {}
template <class tArg>
bool operator() (const tArg &arg) const
{ return !pred(arg); }
};
template <class Pred>
inline Not<Pred> operator! (const Pred &pred)
{
return Not<Pred>(pred);
}
template <class Pred>
Pred operator! (const Not<Pred> &pred)
{
return pred.pred;
}
Note that operators && and || can benefit from this trick likewise.
You can do this:
struct MyPredicate
{
bool positive;
MyPredicate() : positive(true) {}
bool operator() (T1) const {
return original_return_value == positive;
}
bool operator() (T2) const {
return original_return_value == positive;
}
};
inline MyPredicate operator! (MyPredicate p) {
p.positive = !p.positive;
return p;
}
To address your concern of forgetting to use positive, you could try an alternative approach with a wrapper class.
template <class Predicate>
struct NegatablePredicate
{
Predicate pred;
bool positive;
NegatablePredicate(Predicate pred, bool positive) : pred(pred), positive(positive) {}
template <class tArg>
bool operator() (const tArg &arg) const
{ return pred(arg) == positive; }
};
template <class Pred>
inline NegatablePredicate<Pred> operator! (const Pred &pred)
{
return NegatablePredicate<Pred>(pred, false);
}
You can also add an overload for optimisation purposes:
template <class Pred>
inline NegatablePredicate<Pred> operator! (const NegatablePredicate<Pred> &pred)
{
return NegatablePredicate<Pred>(pred.pred, !pred.positive);
}
To address possible concern with the wide scope of the template operator!, you can employ boost::enable_if magic.
You actually can derive from std::unary_function:
template<typename T>
struct MyPredicate : std::unary_function<T, bool>
{
bool operator()(T) const;
};
For simplicity, let's say I want to do implement a function which takes two parameters and predicate which test for equality,
template<typename T, typename TCompare>
bool Eq(const T& a, const T& b, const TCompare& cmp) {
return cmp(a, b);
}
but I also want that operator== is assumed if predicate is not passed.
I tried several different approaches, but all resulted in either syntax error or "operator==" not defined. I even tried replacing the Eq function with a
Nevertheless, I suppose what I want is possible since the big part of STL supports not passing the optional TCompare parameter (std::sort, std::set ...).
UPDATE:
Thanks to levis501 suggestion, this is the best way I have found so far:
template<typename T, typename TCompare>
bool Eq(const T& a, const T& b, const TCompare& cmp) {
return cmp(a, b); // or some lengthy code
}
template<typename T>
bool Eq(const T& a, const T& b) {
static std::equal_to<T> EqCmp;
return Eq(a, b, EqCmp);
}
So, you basically need to create a wrapper which passes std::equal_to, or any other operator-equivalent functor. For some reason, having it as a default argument does not compile when you invoke the function without it.
How about std::equal_to ? http://www.cplusplus.com/reference/std/functional/equal_to/
You can overload functions, no?
// Use the user-supplied TCompare.
template<typename T, typename TCompare>
bool Eq(const T& a, const T& b, TCompare cmp) {
return cmp(a, b);
}
// Use op== for equality otherwise.
template<typename T>
bool Eq(const T& a, const T& b) {
return a == b;
}
If the code calls Eq() with three arguments, the compiler will resolve the call to the first overload. If the code calls Eq() with only two arguments, then the compiler will have to resolve to the second overload.
I don't suppose something like the following would work for you:
#include <functional>
template<typename T, typename TCompare = std::equal_to<T>>
class Math {
public:
static bool Eq(const T& a, const T& b) {
TCompare cmp;
return cmp(a, b);
}
};
int _tmain(int argc, _TCHAR* argv[]) {
Math<int>::Eq(1,1);
return 0;
}
Default template parameters are only allowed on class templates (or at least that's what MSVC 10 says)