Recursive generic function used as a predicate, compilation failure
I am writing a function to compare the contents of two lists. The order of the elements don't matter, so I sort them before I compare. The lists can be of normal types list<int>
, but also be lists of lists list<list<int> >
.
Here is a complete stripped down example:
#include <list>
template <typename T>
bool lessThanInAnyOrder(T lhs, T rhs)
{
return lhs < rhs;
}
template <typename T>
bool lessThanInAnyOrder(std::list<T> 开发者_运维百科lhs, std::list<T> rhs)
{
lhs.sort(lessThanInAnyOrder<T>);
rhs.sort(lessThanInAnyOrder<T>);
//Do comparisons here, but for now just:
return false;
}
int main()
{
std::list<int> list1;
std::list<int> list2;
lessThanInAnyOrder(list1, list2);
}
This compiles in GCC 4.3.3, but in Visual Studio 2008, it gives the following compilation error where I'm calling lhs.sort()
:
error C2660: 'std::list<_Ty>::sort' : function does not take 1 arguments
Any suggestions?
First off: I suppose if you want to compare collections regardless of their ordering, you might be looking for std::set
with the set_difference
, set_intersection
, set_union
and set_symmetric_difference
algorithms
To your question
You're trying to implement sort-by-policy; if you cannot simply specialize std::less<>
(which exists for that exact purpose), you could knock off a custom policy yourself: (code running on codepad.org)
#include <list>
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
namespace applogic
{
template <typename T>
struct sort_policy
{
typedef std::less<T> predicate_t;
};
template <> struct sort_policy<std::string>
{
struct _Cmp { bool operator()(const std::string& a, const std::string& b) { return a.length()>b.length(); } };
typedef _Cmp predicate_t;
};
template <typename C>
void sort(C& cont)
{
typedef typename sort_policy<typename C::value_type>::predicate_t P;
std::sort(cont.begin(), cont.end(), P());
}
template <typename T>
void sort(std::list<T>& cont)
{
typedef typename sort_policy<T>::predicate_t P;
cont.sort(P());
}
}
template <class C>
static void dump(const C& cont, const std::string& msg="")
{
std::cout << msg;
std::copy(cont.begin(), cont.end(), std::ostream_iterator<typename C::value_type>(std::cout, ", "));
std::cout << std::endl;
}
int main()
{
using applogic::sort;
std::vector<int> ints;
ints.push_back(13);
ints.push_back(-3);
ints.push_back(7);
dump(ints, "before: ");
sort(ints);
dump(ints, "after: ");
std::list<std::string> strings;
strings.push_back("very very long");
strings.push_back("tiny");
strings.push_back("medium size");
dump(strings, "before: ");
sort(strings);
dump(strings, "after: ");
return 0;
}
Compilation fails because compiler can't select overloaded 'lessThanInAnyOrder' function to pass to list::sort. You'll have to specify it's type explicitly like here.
template <typename T>
bool lessThanInAnyOrder(std::list<T> lhs, std::list<T> rhs)
{
bool (*comparer)(T, T) = &lessThanInAnyOrder<T>;
lhs.sort(comparer);
rhs.sort(comparer);
//Do comparisons here, but for now just:
return false;
}
Wrap the function in std::ptr_fun
with explicit type arguments:
lhs.sort(std::ptr_fun<T, T>(lessThanInAnyOrder<T>));
My guess, for int
type you can simply write like this:
lhs.sort();
rhs.sort();
Demo.
精彩评论