Last active
April 17, 2018 20:11
-
-
Save MORTAL2000/edd77ec81572788fb8ed03dacc558027 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
#include <iostream> | |
#include <algorithm> | |
#include <utility> | |
#include <map> | |
#include <set> | |
#include <vector> | |
#include <array> | |
#include <type_traits> | |
#include <typeinfo> | |
// String format | |
#ifdef __GNUG__ // GCC | |
#include <cxxabi.h> | |
#include <cstdlib> | |
static std::string readable_name( const char* mangled_name ) | |
{ | |
int status ; | |
char* temp = __cxxabiv1::__cxa_demangle( mangled_name, nullptr, nullptr, &status ) ; | |
if(temp) | |
{ | |
std::string result(temp) ; | |
std::free(temp) ; | |
return result ; | |
} | |
else return mangled_name ; | |
} | |
#else // not GCC | |
inline std::string readable_name( const char* mangled_name ) { return mangled_name ; } | |
#endif // __GNUG__ | |
template <typename T> std::string type_to_string() | |
{ return readable_name( typeid(T).name() ) ; } | |
template <typename T> std::string type_to_string( const T& obj ) | |
{ return readable_name( typeid(obj).name() ) ; } | |
// Trails | |
template <typename T> struct has_find_impl:std::false_type{}; | |
// Associative | |
template <typename T, typename... Args> struct has_find_impl<std::set<T, Args...>>:std::true_type{}; | |
template <typename T, typename... Args> struct has_find_impl<std::map<T, Args...>>:std::true_type{}; | |
template <typename T, typename... Args> struct has_find_impl<std::multiset<T, Args...>>:std::true_type{}; | |
template <typename T, typename... Args> struct has_find_impl<std::multimap<T, Args...>>:std::true_type{}; | |
template <typename T> struct has_find | |
{ | |
static constexpr bool value = has_find_impl<typename std::decay<T>::type>::value; | |
}; | |
// Associative containers | |
template <template <typename...> class Container, typename T, typename... Args> | |
typename std::enable_if<has_find<Container<T, Args...>>::value, bool>::type | |
contains(const Container<T, Args...>& container, const T& value) | |
{ | |
bool result = container.find(value) != container.end(); | |
std::cout << "\tContainer is:\n" << type_to_string(container) << "\n\tResult via Member:\n"; | |
return result; | |
} | |
// Sequence containers | |
template <typename Container> | |
typename std::enable_if<!has_find<Container>::value, bool>::type | |
contains(const Container & container, typename Container::const_reference value) | |
{ | |
bool result = std::find(container.begin(), container.end(), value) != container.end(); // or std::any_of | |
std::cout << "\tContainer is:\n" << type_to_string(container) << "\n\tResult via Algorithm:\n"; | |
return result; | |
} | |
int main() | |
{ | |
std::cout << std::boolalpha; | |
std::array<int, 3> a = { 1, 2, 3 }; | |
std::cout << contains(a, 0) << "\n\n"; | |
std::cout << contains(a, 1) << "\n\n"; | |
std::vector<int> v = { 1, 2, 3 }; | |
std::cout << contains(v, 0) << "\n\n"; | |
std::cout << contains(v, 1) << "\n\n"; | |
std::set<int> s = { 1, 2, 3 }; | |
std::cout << contains(s, 0) << "\n\n"; | |
std::cout << contains(s, 1) << "\n\n"; | |
std::map<int, int> m = { { 1, 1}, { 2, 2}, { 3, 3} }; | |
std::cout << contains(m, 0) << "\n\n"; | |
std::cout << contains(m, 1) << "\n\n"; | |
} |
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
#include <iostream> | |
#include <algorithm> | |
#include <utility> | |
#include <map> | |
#include <set> | |
#include <vector> | |
#include <array> | |
#include <type_traits> | |
#include <typeinfo> | |
template <typename T> struct has_find_impl:std::false_type{}; | |
template <typename T, typename... Args> struct has_find_impl<std::set<T, Args...>>:std::true_type{}; | |
template <typename T, typename... Args> struct has_find_impl<std::map<T, Args...>>:std::true_type{}; | |
template <typename T, typename... Args> struct has_find_impl<std::multiset<T, Args...>>:std::true_type{}; | |
template <typename T, typename... Args> struct has_find_impl<std::multimap<T, Args...>>:std::true_type{}; | |
template <typename T> using has_find = has_find_impl<typename std::decay<T>::type>; | |
template <class Container> | |
typename std::enable_if<has_find<Container>::value, bool>::type | |
contains_impl(const Container& c, const typename Container::key_type& key) | |
{ | |
return c.find(key) != c.cend(); | |
} | |
template <class Container> | |
typename std::enable_if<!has_find<Container>::value, bool>::type | |
contains_impl(const Container& c, typename Container::const_reference key) | |
{ | |
return std::find(c.cbegin(), c.cend(), key) != c.cend(); | |
} | |
template <class Container, class T> | |
bool contains(const Container& c, const T& key) | |
{ | |
return contains_impl(c, key); | |
} | |
int main() | |
{ | |
std::cout << std::boolalpha; | |
std::array<int, 3> a = { 1, 2, 3 }; | |
std::cout << contains(a, 0) << "\n"; | |
std::cout << contains(a, 1) << "\n\n"; | |
std::vector<int> v = { 1, 2, 3 }; | |
std::cout << contains(v, 0) << "\n"; | |
std::cout << contains(v, 1) << "\n\n"; | |
std::set<int> s = { 1, 2, 3 }; | |
std::cout << contains(s, 0) << "\n"; | |
std::cout << contains(s, 1) << "\n\n"; | |
std::map<int, int> m = { { 1, 1}, { 2, 2}, { 3, 3} }; | |
std::cout << contains(m, 0) << "\n"; | |
std::cout << contains(m, 1) << "\n\n"; | |
} |
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
#include <iostream> | |
#include <algorithm> | |
#include <utility> | |
#include <map> | |
#include <set> | |
#include <vector> | |
#include <array> | |
#include <type_traits> | |
template <typename ... Ts> | |
struct voider{ using type = void; }; | |
template <typename... Ts> | |
using void_t = typename voider<Ts...>::type; | |
template<typename C, typename T, typename X = void_t<>> | |
struct has_find_member : std::false_type {}; | |
template<typename C, typename T> | |
#define TRAIT_CASE decltype(std::declval<C>().find(std::declval<const T&>())) | |
struct has_find_member<C, T, void_t<TRAIT_CASE>> : std::true_type {}; | |
template <typename C, typename T> | |
bool contains_impl(C&& c, T&& t, std::true_type) | |
{ | |
return c.end() != c.find(std::forward<T>(t)); | |
} | |
template <typename C, typename T> | |
bool contains_impl(C&& c, T&& t, std::false_type) | |
{ | |
return c.end() != std::find(c.begin(), c.end(), std::forward<T>(t)); | |
} | |
template <typename C, typename T> | |
auto contains(const C& container, const T& key) | |
{ | |
return contains_impl(container, key, has_find_member<C, T>{}); | |
} | |
int main() | |
{ | |
std::cout << std::boolalpha; | |
std::array<int, 3> a = {{ 1, 2, 3 }}; | |
std::cout << contains(a, 0) << "\n"; | |
std::cout << contains(a, 1) << "\n\n"; | |
std::vector<int> v = { 1, 2, 3 }; | |
std::cout << contains(v, 0) << "\n"; | |
std::cout << contains(v, 1) << "\n\n"; | |
std::set<int> s = { 1, 2, 3 }; | |
std::cout << contains(s, 0) << "\n"; | |
std::cout << contains(s, 1) << "\n\n"; | |
std::map<int, int> m = { { 1, 1}, { 2, 2}, { 3, 3} }; | |
std::cout << contains(m, 0) << "\n"; | |
std::cout << contains(m, 1) << "\n"; | |
} |
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
#include <iostream> | |
#include <vector> | |
#include <set> | |
#include <array> | |
#include <map> | |
#include <algorithm> | |
#include <type_traits> | |
#include <utility> | |
template <typename...> | |
using void_t = void; | |
template <typename AlwaysVoid, template <typename...> class Operation, typename... Args> | |
struct detect_impl : std::false_type {}; | |
template <template <typename...> class Operation, typename... Args> | |
struct detect_impl<void_t<Operation<Args...>>, Operation, Args...> : std::true_type {}; | |
template <template <typename...> class Operation, typename... Args> | |
using detect = detect_impl<void, Operation, Args...>; | |
// ----------------------------------------------------------------- | |
template <typename T, typename... Us> | |
using has_find = decltype(std::declval<T>().find(std::declval<Us>()...)); | |
template <class Container, typename T> | |
typename std::enable_if<detect<has_find, Container, T>::value, bool>::type | |
contains(const Container& c, const T& key) | |
{ | |
return c.cend() != c.find(key); | |
} | |
template <class Container, typename T> | |
typename std::enable_if<!detect<has_find, Container, T>::value, bool>::type | |
contains(const Container& c, const T& key) | |
{ | |
return c.cend() != std::find(c.cbegin(), c.cend(), key); | |
} | |
int main() | |
{ | |
std::cout << std::boolalpha; | |
std::array<int, 3> a = { 1, 2, 3 }; | |
std::cout << contains(a, 0) << "\n\n"; | |
std::cout << contains(a, 1) << "\n\n"; | |
std::vector<int> v = { 1, 2, 3 }; | |
std::cout << contains(v, 0) << "\n\n"; | |
std::cout << contains(v, 1) << "\n\n"; | |
std::set<int> s = { 1, 2, 3 }; | |
std::cout << contains(s, 0) << "\n\n"; | |
std::cout << contains(s, 1) << "\n\n"; | |
std::map<int, int> m = { { 1, 1}, { 2, 2}, { 3, 3} }; | |
std::cout << contains(m, 0) << "\n\n"; | |
std::cout << contains(m, 1) << "\n\n"; | |
} |
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
#include <iostream> | |
#include <algorithm> | |
#include <utility> | |
#include <map> | |
#include <set> | |
#include <vector> | |
#include <array> | |
#include <type_traits> | |
#include <typeinfo> | |
template <class Container> | |
inline auto contains(Container const& c, typename Container::key_type const& key, int) | |
noexcept(noexcept(c.end(), c.find(key))) ->decltype(c.find(key), true) | |
{ | |
bool result = c.find(key) != c.cend(); | |
std::cout << "\tContainer is:\n" << typeid(c).name() << "\nResult via Member:\n"; | |
return result; | |
} | |
template <class Container> | |
inline auto contains(Container const& c, typename Container::value_type const& key, long) | |
noexcept(noexcept(c.end(), ::std::find(c.begin(), c.end(), key))) | |
{ | |
bool result = std::find(c.cbegin(), c.cend(), key) != c.cend(); // or std::any_of | |
std::cout << "\tContainer is:\n" <<typeid(c).name() << "\nResult via Algorithm:\n"; | |
return result; | |
} | |
template <class Container, typename T> | |
inline auto contains(Container const& c, T const& key) | |
noexcept(noexcept(contains(c, key, 0))) | |
{ | |
return contains(c, key, 0); | |
} | |
int main() | |
{ | |
std::cout << std::boolalpha; | |
std::array<int, 3> a = { 1, 2, 3 }; | |
std::cout << contains(a, 0) << "\n"; | |
std::cout << contains(a, 1) << "\n\n"; | |
std::vector<int> v = { 1, 2, 3 }; | |
std::cout << contains(v, 0) << "\n"; | |
std::cout << contains(v, 1) << "\n\n"; | |
std::set<int> s = { 1, 2, 3 }; | |
std::cout << contains(s, 0) << "\n"; | |
std::cout << contains(s, 1) << "\n\n"; | |
std::map<int, int> m = { { 1, 1}, { 2, 2}, { 3, 3} }; | |
std::cout << contains(m, 0) << "\n"; | |
std::cout << contains(m, 1) << "\n\n"; | |
} |
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
// doesn't work VC++ | |
#include <iostream> | |
#include <algorithm> | |
#include <utility> | |
#include <map> | |
#include <set> | |
#include <vector> | |
#include <array> | |
#include <tuple> | |
#include <functional> | |
#include <type_traits> | |
template<bool b> struct static_if_t {}; | |
template<bool b> struct static_else_if_t {}; | |
struct static_unsolved_t {}; | |
template<class Op> | |
struct static_solved_t | |
{ | |
Op value; | |
template<class...Ts> | |
constexpr decltype(auto) operator()(Ts&&...ts) | |
{ | |
return value(std::forward<Ts>(ts)...); | |
} | |
template<class Rhs> | |
constexpr static_solved_t&& operator->*(Rhs&&) | |
{ | |
return std::move(*this); | |
} | |
}; | |
template<class F> | |
constexpr | |
static_solved_t<std::decay_t<F>> static_solved(F&& f) | |
{ | |
return {std::forward<F>(f)}; | |
} | |
template<class F> | |
constexpr | |
auto operator->*(static_if_t<true>, F&& f) | |
{ | |
return static_solved(std::forward<F>(f)); | |
} | |
template<class F> | |
constexpr | |
static_unsolved_t operator->*(static_if_t<false>, F&&) | |
{ | |
return {}; | |
} | |
constexpr | |
static_if_t<true> operator->*(static_unsolved_t, static_else_if_t<true>) | |
{ | |
return {}; | |
} | |
constexpr | |
static_unsolved_t operator->*(static_unsolved_t, static_else_if_t<false>) | |
{ | |
return {}; | |
} | |
//template<bool b> | |
//constexpr static_if_t<b> static_if{}; | |
//template<bool b> | |
//constexpr static_else_if_t<b> static_else_if{}; | |
//constexpr static_else_if_t<true> static_else{}; | |
template <typename...> | |
using void_t = void; | |
template <typename AlwaysVoid, template <typename...> class Operation, typename... Args> | |
struct detect_impl : std::false_type {}; | |
template <template <typename...> class Operation, typename... Args> | |
struct detect_impl<void_t<Operation<Args...>>, Operation, Args...> : std::true_type {}; | |
template <template <typename...> class Operation, typename... Args> | |
using detect = detect_impl<void, Operation, Args...>; | |
template <typename T, typename... Us> | |
using has_find = decltype(std::declval<T>().find(std::declval<Us>()...)); | |
template <class Container, typename T> | |
auto contains(const Container& c, const T& key) | |
{ | |
auto op = | |
static_if_t<detect<has_find, Container, T>{}>{}->* | |
[&](auto& cont) | |
{ | |
return cont.end() != cont.find(key); | |
} | |
//->*static_else_if_t<!detect<has_find, Container, T>{}>{}->* | |
//[&](auto& cont) | |
//{ | |
// return cont.end() != ::std::find(cont.begin(), cont.end(), key); | |
//}; | |
->*static_else_if_t<true>{}->* | |
[&](auto& cont) | |
{ | |
return cont.end() != ::std::find(cont.begin(), cont.end(), key); | |
}; | |
return op(c); | |
} | |
int main() | |
{ | |
std::cout << std::boolalpha; | |
std::array<int, 3> a = {{ 1, 2, 3 }}; | |
std::cout << contains(a, 0) << "\n"; | |
std::cout << contains(a, 1) << "\n\n"; | |
std::vector<int> v = { 1, 2, 3 }; | |
std::cout << contains(v, 0) << "\n"; | |
std::cout << contains(v, 1) << "\n\n"; | |
std::set<int> s = { 1, 2, 3 }; | |
std::cout << contains(s, 0) << "\n"; | |
std::cout << contains(s, 1) << "\n\n"; | |
std::map<int, int> m = { { 1, 1}, { 2, 2}, { 3, 3} }; | |
std::cout << contains(m, 0) << "\n"; | |
std::cout << contains(m, 1) << "\n"; | |
} |
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
#include <iostream> | |
#include <vector> | |
#include <set> | |
#include <array> | |
#include <map> | |
#include <algorithm> | |
#include <type_traits> | |
#include <utility> | |
// condintional toolkit | |
template <bool B, typename T, typename F> | |
struct conditional_impl | |
{ | |
using type = F; | |
constexpr static F pick(T&& , F&& f) | |
{ | |
return std::forward<F>(f); | |
} | |
}; | |
template <typename T, typename F> | |
struct conditional_impl<true, T, F> | |
{ | |
using type = T; | |
constexpr static T pick(T&& t, F&&) | |
{ | |
return std::forward<T>(t); | |
} | |
}; | |
template <bool B, typename T, typename F> | |
auto conditional(T&& t, F&& f) | |
{ | |
return conditional_impl<B,T,F>::pick(std::forward<T>(t), std::forward<F>(f)); | |
} | |
// detect toolkit | |
template <typename...> | |
using void_t = void; | |
template <typename AlwaysVoid, template <typename...> class Operation, typename... Args> | |
struct detect_impl : std::false_type {}; | |
template <template <typename...> class Operation, typename... Args> | |
struct detect_impl<void_t<Operation<Args...>>, Operation, Args...> : std::true_type {}; | |
template <template <typename...> class Operation, typename... Args> | |
using detect_t = detect_impl<void, Operation, Args...>; | |
// ----------------------------------------------------------------- | |
template <typename T, typename... Us> | |
using has_find_t = decltype(std::declval<T>().find(std::declval<Us>()...)); | |
template <class C, typename T> | |
struct has_find | |
{ | |
constexpr static auto value = detect_t<has_find_t, C, T>::value; | |
}; | |
// ----------------------------------------------------------------- | |
template <class Container, typename T> | |
auto contains(const Container& c, const T& key) | |
{ | |
auto op = conditional<has_find<Container, T>::value> | |
( | |
[] (auto&& cont, auto&& k) { return cont.end() != cont.find(k); }, | |
[] (auto&& cont, auto&& k) { return cont.end() != ::std::find(cont.begin(), cont.end(), k); } | |
); | |
return op(c, key); | |
} | |
int main() | |
{ | |
std::cout << std::boolalpha; | |
std::array<int, 3> a = {{ 1, 2, 3 }}; | |
std::cout << contains(a, 0) << "\n"; | |
std::cout << contains(a, 1) << "\n\n"; | |
std::vector<int> v = { 1, 2, 3 }; | |
std::cout << contains(v, 0) << "\n"; | |
std::cout << contains(v, 1) << "\n\n"; | |
std::set<int> s = { 1, 2, 3 }; | |
std::cout << contains(s, 0) << "\n"; | |
std::cout << contains(s, 1) << "\n\n"; | |
std::map<int, int> m = { { 1, 1}, { 2, 2}, { 3, 3} }; | |
std::cout << contains(m, 0) << "\n"; | |
std::cout << contains(m, 1) << "\n"; | |
} |
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
#include <iostream> | |
#include <algorithm> | |
#include <utility> | |
#include <map> | |
#include <set> | |
#include <vector> | |
#include <array> | |
#include <type_traits> | |
// Detect if container has C::find | |
template <typename C> decltype(std::declval<C>().find(0), std::true_type{}) test(int); | |
template <typename C> std::false_type test(...); | |
template <typename C> using has_find = decltype(test<C>(0)); | |
// Based on std::conditional | |
template <bool B, typename T, typename F> | |
struct conditional_impl | |
{ | |
constexpr static F pick(T&& , F&& f) | |
{ | |
return std::forward<F>(f); | |
} | |
}; | |
template <typename T, typename F> | |
struct conditional_impl<true, T, F> | |
{ | |
constexpr static T pick(T&& t, F&&) | |
{ | |
return std::forward<T>(t); | |
} | |
}; | |
template <bool B, typename T, typename F> | |
auto conditional(T&& t, F&& f) | |
{ | |
return conditional_impl<B,T,F>::pick(std::forward<T>(t), std::forward<F>(f)); | |
} | |
// one for all and all for one | |
template <typename C, typename T> | |
auto contains(const C& container, const T& key) | |
{ | |
static auto first = [] (auto&& c, auto&& k) | |
{ | |
return c.end() != c.find(k); | |
}; | |
static auto second = [] (auto&& c, auto&& k) | |
{ | |
return c.end() != std::find(c.begin(), c.end(), k); | |
}; | |
auto op = conditional<has_find<C>::value>(first, second); | |
return op(container, key); | |
} | |
int main() | |
{ | |
std::cout << std::boolalpha; | |
std::array<int, 3> a = {{ 1, 2, 3 }}; | |
std::cout << contains(a, 0) << "\n"; | |
std::cout << contains(a, 1) << "\n\n"; | |
std::vector<int> v = { 1, 2, 3 }; | |
std::cout << contains(v, 0) << "\n"; | |
std::cout << contains(v, 1) << "\n\n"; | |
std::set<int> s = { 1, 2, 3 }; | |
std::cout << contains(s, 0) << "\n"; | |
std::cout << contains(s, 1) << "\n\n"; | |
std::map<int, int> m = { { 1, 1}, { 2, 2}, { 3, 3} }; | |
std::cout << contains(m, 0) << "\n"; | |
std::cout << contains(m, 1) << "\n"; | |
} |
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
#include <iostream> | |
#include <algorithm> | |
#include <utility> | |
#include <map> | |
#include <set> | |
#include <vector> | |
#include <array> | |
#include <type_traits> | |
template <typename C> decltype(std::declval<C>().find(0), std::true_type{}) test(int); | |
template <typename C> std::false_type test(...); | |
template <typename C> using has_find = decltype(test<C>(0)); | |
template <bool B, typename T, typename F> | |
std::enable_if_t<std::integral_constant<bool, B>::value, T> | |
conditional(T&& t, F&&) | |
{ | |
return std::forward<T>(t); | |
} | |
template <bool B, typename T, typename F> | |
std::enable_if_t<!std::integral_constant<bool, B>::value, F> | |
conditional(T&&, F&& f) | |
{ | |
return std::forward<F>(f); | |
} | |
template <typename C, typename T> | |
auto contains(const C& container, const T& key) | |
{ | |
static auto first = [] (auto&& c, auto&& k) | |
{ | |
return c.end() != c.find(k); | |
}; | |
static auto second = [] (auto&& c, auto&& k) | |
{ | |
return c.end() != std::find(c.begin(), c.end(), k); | |
}; | |
auto op = conditional<has_find<C>::value>(first, second); | |
return op(container, key); | |
} | |
int main() | |
{ | |
std::cout << std::boolalpha; | |
std::array<int, 3> a = {{ 1, 2, 3 }}; | |
std::cout << contains(a, 0) << "\n"; | |
std::cout << contains(a, 1) << "\n\n"; | |
std::vector<int> v = { 1, 2, 3 }; | |
std::cout << contains(v, 0) << "\n"; | |
std::cout << contains(v, 1) << "\n\n"; | |
std::set<int> s = { 1, 2, 3 }; | |
std::cout << contains(s, 0) << "\n"; | |
std::cout << contains(s, 1) << "\n\n"; | |
std::map<int, int> m = { { 1, 1}, { 2, 2}, { 3, 3} }; | |
std::cout << contains(m, 0) << "\n"; | |
std::cout << contains(m, 1) << "\n"; | |
} |
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
#include <iostream> | |
#include <algorithm> | |
#include <utility> | |
#include <map> | |
#include <set> | |
#include <vector> | |
#include <array> | |
#include <type_traits> | |
template <typename C> decltype(std::declval<C>().find(0), std::true_type{}) test(int); | |
template <typename C> std::false_type test(...); | |
template <typename C> using has_find = decltype(test<C>(0)); | |
template <typename T, typename F> | |
T&& conditional(std::true_type, T&& t, F&& f) | |
{ | |
return std::forward<T>(t); | |
} | |
template <typename T, typename F> | |
F&& conditional(std::false_type, T&& t, F&& f) | |
{ | |
return std::forward<F>(f); | |
} | |
template <typename C, typename T> | |
auto contains(const C& container, const T& key) | |
{ | |
static auto first = [] (auto&& c, auto&& k) | |
{ | |
return c.end() != c.find(k); | |
}; | |
static auto second = [] (auto&& c, auto&& k) | |
{ | |
return c.end() != std::find(c.begin(), c.end(), k); | |
}; | |
auto op = conditional(has_find<C>{},first, second); | |
return op(container, key); | |
} | |
int main() | |
{ | |
std::cout << std::boolalpha; | |
std::array<int, 3> a = {{ 1, 2, 3 }}; | |
std::cout << contains(a, 0) << "\n"; | |
std::cout << contains(a, 1) << "\n\n"; | |
std::vector<int> v = { 1, 2, 3 }; | |
std::cout << contains(v, 0) << "\n"; | |
std::cout << contains(v, 1) << "\n\n"; | |
std::set<int> s = { 1, 2, 3 }; | |
std::cout << contains(s, 0) << "\n"; | |
std::cout << contains(s, 1) << "\n\n"; | |
std::map<int, int> m = { { 1, 1}, { 2, 2}, { 3, 3} }; | |
std::cout << contains(m, 0) << "\n"; | |
std::cout << contains(m, 1) << "\n"; | |
} |
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
#include <iostream> | |
#include <algorithm> | |
#include <utility> | |
#include <map> | |
#include <set> | |
#include <vector> | |
#include <array> | |
#include <type_traits> | |
template <typename ... Ts> | |
struct voider | |
{ | |
using type = void; | |
}; | |
template <typename... Ts> using void_t = typename voider<Ts...>::type; | |
template<class C, class T, class X = void_t<>> | |
struct has_find_member : std::false_type {}; | |
template<class C, class T> | |
#define TRAIT_CASE decltype(std::declval<C>().find(std::declval<const T&>())) | |
struct has_find_member<C, T, void_t<TRAIT_CASE>> : std::true_type {}; | |
template <typename C, typename T> | |
std::enable_if_t<has_find_member<C, T>::value, bool> | |
contains_impl(C&& c, T&& t) | |
{ | |
return c.end() != c.find(std::forward<T>(t)); | |
} | |
template <typename C, typename T> | |
std::enable_if_t<!has_find_member<C, T>::value, bool> | |
contains_impl(C&& c, T&& t) | |
{ | |
return c.end() != std::find(c.begin(), c.end(), std::forward<T>(t)); | |
} | |
template <typename C, typename T> | |
auto contains(const C& container, const T& key) | |
{ | |
return contains_impl(container, key); | |
} | |
int main() | |
{ | |
std::cout << std::boolalpha; | |
std::array<int, 3> a = { { 1, 2, 3 } }; | |
std::cout << contains(a, 0) << "\n"; | |
std::cout << contains(a, 1) << "\n\n"; | |
std::vector<int> v = { 1, 2, 3 }; | |
std::cout << contains(v, 0) << "\n"; | |
std::cout << contains(v, 1) << "\n\n"; | |
std::set<int> s = { 1, 2, 3 }; | |
std::cout << contains(s, 0) << "\n"; | |
std::cout << contains(s, 1) << "\n\n"; | |
std::map<int, int> m = { { 1, 1 },{ 2, 2 },{ 3, 3 } }; | |
std::cout << contains(m, 0) << "\n"; | |
std::cout << contains(m, 1) << "\n"; | |
} |
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
#include <iostream> | |
#include <algorithm> | |
#include <utility> | |
#include <map> | |
#include <set> | |
#include <vector> | |
#include <array> | |
#include <type_traits> | |
template <typename T> struct has_find_impl:std::false_type{}; | |
template <typename T, typename... Args> struct has_find_impl<std::set<T, Args...>>:std::true_type{}; | |
template <typename T, typename... Args> struct has_find_impl<std::map<T, Args...>>:std::true_type{}; | |
template <typename T, typename... Args> struct has_find_impl<std::multiset<T, Args...>>:std::true_type{}; | |
template <typename T, typename... Args> struct has_find_impl<std::multimap<T, Args...>>:std::true_type{}; | |
template <typename T> using has_find = has_find_impl<typename std::decay<T>::type>; | |
template <class Container> | |
bool contains_impl(const Container& c, const typename Container::key_type& key, std::true_type) | |
{ | |
return c.find(key) != c.cend(); | |
} | |
template <class Container> | |
bool contains_impl(const Container& c, typename Container::const_reference key, std::false_type) | |
{ | |
return std::find(c.cbegin(), c.cend(), key) != c.cend(); | |
} | |
template <class Container, class T> | |
bool contains(const Container& c, const T& key) | |
{ | |
return contains_impl(c, key, has_find<Container>{}); | |
} | |
int main() | |
{ | |
std::cout << std::boolalpha; | |
std::array<int, 3> a = { 1, 2, 3 }; | |
std::cout << contains(a, 0) << "\n"; | |
std::cout << contains(a, 1) << "\n\n"; | |
std::vector<int> v = { 1, 2, 3 }; | |
std::cout << contains(v, 0) << "\n"; | |
std::cout << contains(v, 1) << "\n\n"; | |
std::set<int> s = { 1, 2, 3 }; | |
std::cout << contains(s, 0) << "\n"; | |
std::cout << contains(s, 1) << "\n\n"; | |
std::map<int, int> m = { { 1, 1}, { 2, 2}, { 3, 3} }; | |
std::cout << contains(m, 0) << "\n"; | |
std::cout << contains(m, 1) << "\n\n"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment