Last active
August 29, 2015 14:18
-
-
Save kaini/1296de09cc2a97216339 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///// 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