Last active
March 27, 2020 06:02
-
-
Save hikarin522/68660a830c44697075739cd195f3f87c 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
#pragma once | |
// C++20 統一コンテナ削除 | |
// https://ja.cppreference.com/w/cpp/experimental/lib_extensions_2#Uniform_container_erasure | |
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1209r0.html | |
#include <utility> | |
#include <iterator> | |
#include <algorithm> | |
#include <type_traits> | |
namespace std { | |
template <class T, class Allocator> | |
class vector; | |
template <class T, class Allocator> | |
class deque; | |
template <class charT, class traits, class Allocator> | |
class basic_string; | |
template <class T, class Allocator> | |
class list; | |
template <class T, class Allocator> | |
class forward_list; | |
template <class Key, class T, class Compare, class Allocator> | |
class map; | |
template <class Key, class T, class Compare, class Allocator> | |
class multimap; | |
template <class Key, class Compare, class Allocator> | |
class set; | |
template <class Key, class Compare, class Allocator> | |
class multiset; | |
template <class Key, class T, class Hash, class Pred, class Allocator> | |
class unordered_map; | |
template <class Key, class T, class Hash, class Pred, class Allocator> | |
class unordered_multimap; | |
template <class Key, class Hash, class Pred, class Allocator> | |
class unordered_set; | |
template <class Key, class Hash, class Pred, class Allocator> | |
class unordered_multiset; | |
} | |
namespace std_erase_detail { | |
template <class T> | |
struct is_vector: std::false_type { }; | |
#ifndef __cpp_lib_erase_if | |
template <class ...T> | |
struct is_vector<std::vector<T...>>: std::true_type { }; | |
template <class ...T> | |
struct is_vector<std::deque<T...>>: std::true_type { }; | |
template <class ...T> | |
struct is_vector<std::basic_string<T...>>: std::true_type { }; | |
#endif // __cpp_lib_erase_if | |
template <class T> | |
struct is_list: std::false_type { }; | |
#ifndef __cpp_lib_erase_if | |
template <class ...T> | |
struct is_list<std::list<T...>>: std::true_type { }; | |
template <class ...T> | |
struct is_list<std::forward_list<T...>>: std::true_type { }; | |
#endif // __cpp_lib_erase_if | |
template <class T> | |
struct is_map: std::false_type { }; | |
#ifndef __cpp_lib_erase_if | |
template <class ...T> | |
struct is_map<std::map<T...>>: std::true_type { }; | |
template <class ...T> | |
struct is_map<std::multimap<T...>>: std::true_type { }; | |
template <class ...T> | |
struct is_map<std::set<T...>>: std::true_type { }; | |
template <class ...T> | |
struct is_map<std::multiset<T...>>: std::true_type { }; | |
template <class ...T> | |
struct is_map<std::unordered_map<T...>>: std::true_type { }; | |
template <class ...T> | |
struct is_map<std::unordered_multimap<T...>>: std::true_type { }; | |
template <class ...T> | |
struct is_map<std::unordered_set<T...>>: std::true_type { }; | |
template <class ...T> | |
struct is_map<std::unordered_multiset<T...>>: std::true_type { }; | |
#endif // __cpp_lib_erase_if | |
} // namespace std_erase_detail | |
namespace std { | |
template <class C, class U, std::enable_if_t<std_erase_detail::is_vector<C>::value, std::nullptr_t> = nullptr> | |
auto erase(C &c, const U &val) { | |
return c.erase(std::remove(std::begin(c), std::end(c), val), std::end(c)); | |
} | |
template <class C, class Pred, std::enable_if_t<std_erase_detail::is_vector<C>::value, std::nullptr_t> = nullptr> | |
auto erase_if(C &c, const Pred &pred) { | |
return c.erase(std::remove_if(std::begin(c), std::end(c), pred), std::end(c)); | |
} | |
template <class C, class U, std::enable_if_t<std_erase_detail::is_list<C>::value, std::nullptr_t> = nullptr> | |
auto erase(C &c, const U &val) { | |
return c.remove(val); | |
} | |
template <class C, class Pred, std::enable_if_t<std_erase_detail::is_list<C>::value, std::nullptr_t> = nullptr> | |
auto erase_if(C &c, const Pred &pred) { | |
return c.remove_if(pred); | |
} | |
template <class C, class Pred, std::enable_if_t<std_erase_detail::is_map<C>::value, std::nullptr_t> = nullptr> | |
auto erase_if(C &c, const Pred &pred) { | |
auto count = 0; | |
for (auto i = std::begin(c), last = std::end(c); i != last;) { | |
if (pred(*i)) { | |
i = c.erase(i); | |
++count; | |
} else { | |
++i; | |
} | |
} | |
return count; | |
} | |
} // namespace std |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment