Skip to content

Instantly share code, notes, and snippets.

@kaini
Last active August 29, 2015 14:18
Show Gist options
  • Save kaini/1296de09cc2a97216339 to your computer and use it in GitHub Desktop.
Save kaini/1296de09cc2a97216339 to your computer and use it in GitHub Desktop.
///// IMPLEMENTATION BELOW
// (If you want to build this just move main at the end of the file)
int main()
{
using namespace std;
vector<int> vi{2,5,7,45,3,45,6,7,8,7,6,5,3,2,5,8};
sort(begin(vi), end(vi), comparing([](int &a) { return make_tuple(a % 5, a); }));
sort(begin(vi), end(vi), comparing(&mul2, greater<>()));
print_vector(vi);
vector<mystruct> vs;
vs.emplace_back("a");
vs.emplace_back("tzu");
vs.emplace_back("qw");
vs.emplace_back("ghjkl");
vs.emplace_back("vbnm");
sort(begin(vs), end(vs), comparing([](mystruct &s) { return s.name; }, greater<>()));
sort(begin(vs), end(vs), comparing(&mystruct::get_name, greater<>()));
sort(begin(vs), end(vs), comparing(&mystruct::name, greater<>()));
print_vector(vs);
sort(begin(vs), end(vs), comparing([](mystruct &s) { return s.name; }));
sort(begin(vs), end(vs), comparing(&mystruct::get_name));
sort(begin(vs), end(vs), comparing(&mystruct::name));
print_vector(vs);
sort(begin(vs), end(vs),
comparing(&mystruct::get_name,
comparing(&string::size,
greater<>())));
print_vector(vs);
vector<shared_ptr<mystruct>> vsptr;
vector<unique_ptr<mystruct>> vuptr;
vector<mystruct *> vrptr;
for (auto &v : vs)
{
vsptr.emplace_back(make_shared<mystruct>(v.name));
vuptr.emplace_back(make_unique<mystruct>(v.name));
vrptr.emplace_back(&v);
}
sort(begin(vsptr), end(vsptr), comparing_deref(&mystruct::name));
sort(begin(vuptr), end(vuptr), comparing_deref(&mystruct::get_name, std::greater<>()));
sort(begin(vrptr), end(vrptr), comparing_deref([](const auto &s) { return s.name; }));
print_vector_deref(vsptr);
print_vector_deref(vuptr);
print_vector_deref(vrptr);
return EXIT_SUCCESS;
}
template <typename T>
static void print_vector(const std::vector<T> &v)
{
for (const auto &i : v)
{
std::cout << i << " ";
}
std::cout << std::endl;
}
template <typename T>
static void print_vector_deref(const std::vector<T> &v)
{
for (const auto &i : v)
{
std::cout << *i << " ";
}
std::cout << std::endl;
}
struct mystruct
{
mystruct(std::string name) : name(std::move(name)) {}
const std::string &get_name() const { return name; }
std::string name;
mystruct(const mystruct &) = delete;
mystruct(mystruct &&) = default;
mystruct &operator=(const mystruct &) = delete;
mystruct &operator=(mystruct &&) = default;
};
std::ostream &operator<<(std::ostream &out, const mystruct &s)
{
return out << s.name;
}
static int mul2(int i)
{
return i * 2;
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <type_traits>
#include <cmath>
#include <memory>
template <typename Mapping, typename Comp, typename Enable = void>
class comparing_impl
{
public:
comparing_impl(Mapping mapping, Comp comp) : mapping(mapping), comp(comp) {}
template <typename Src>
bool operator()(Src &&lhs, Src &&rhs) const
{
return comp(
mapping(std::forward<Src>(lhs)),
mapping(std::forward<Src>(rhs)));
}
private:
Mapping mapping;
Comp comp;
};
template <typename Mapping, typename Comp>
class comparing_impl<Mapping, Comp, typename std::enable_if<std::is_member_function_pointer<Mapping>::value>::type>
{
public:
comparing_impl(Mapping mapping, Comp comp) : mapping(mapping), comp(comp) {}
template <typename Src>
bool operator()(Src &&lhs, Src &&rhs) const
{
return comp(
(std::forward<Src>(lhs).*mapping)(),
(std::forward<Src>(rhs).*mapping)());
}
private:
Mapping mapping;
Comp comp;
};
template <typename Mapping, typename Comp>
class comparing_impl<Mapping, Comp, typename std::enable_if<std::is_member_object_pointer<Mapping>::value>::type>
{
public:
comparing_impl(Mapping mapping, Comp comp) : mapping(mapping), comp(comp) {}
template <typename Src>
bool operator()(Src &&lhs, Src &&rhs) const
{
return comp(
std::forward<Src>(lhs).*mapping,
std::forward<Src>(rhs).*mapping);
}
private:
Mapping mapping;
Comp comp;
};
template <typename Mapping, typename Enable = void>
class comparing_impl_less
{
public:
comparing_impl_less(Mapping mapping) : mapping(mapping) {}
template <typename Src>
bool operator()(Src &&lhs, Src &&rhs) const
{
return std::less<>()(
mapping(std::forward<Src>(lhs)),
mapping(std::forward<Src>(rhs)));
}
private:
Mapping mapping;
};
template <typename Mapping>
class comparing_impl_less<Mapping, typename std::enable_if<std::is_member_function_pointer<Mapping>::value>::type>
{
public:
comparing_impl_less(Mapping mapping) : mapping(mapping) {}
template <typename Src>
bool operator()(Src &&lhs, Src &&rhs) const
{
return std::less<>()(
(std::forward<Src>(lhs).*mapping)(),
(std::forward<Src>(rhs).*mapping)());
}
private:
Mapping mapping;
};
template <typename Mapping>
class comparing_impl_less<Mapping, typename std::enable_if<std::is_member_object_pointer<Mapping>::value>::type>
{
public:
comparing_impl_less(Mapping mapping) : mapping(mapping) {}
template <typename Src>
bool operator()(Src &&lhs, Src &&rhs) const
{
return std::less<>()(
(std::forward<Src>(lhs).*mapping),
(std::forward<Src>(rhs).*mapping));
}
private:
Mapping mapping;
};
const auto deref = [](auto &p) -> auto & { return *p; };
template <typename Mapping>
auto comparing(Mapping map_fn)
{
return comparing_impl_less<Mapping>(map_fn);
}
template <typename Mapping, typename Comp>
auto comparing(Mapping map_fn, Comp comp)
{
return comparing_impl<Mapping, Comp>(map_fn, comp);
}
template <typename Mapping>
auto comparing_deref(Mapping map_fn)
{
return comparing(deref, comparing(map_fn));
}
template <typename Mapping, typename Comp>
auto comparing_deref(Mapping map_fn, Comp comp)
{
return comparing(deref, comparing(map_fn, comp));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment