#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <type_traits>
template <typename T>
class has_find {
template <typename C> static std::true_type test( decltype(&C::find) ) ;
template <typename C> static std::false_type test(...);
public:
using type = decltype(test<T>(nullptr));
static const bool value = type();
};
template <typename T>
int foo( const T & t ) { return 1; }
// overload for std::vector
template <class T>
int foo( const std::vector< T > & vec ) { return 2; }
template <class T, class U>
int foo( const std::map< T, U > & vec ) { return 3; }
template<class T>
int foo(const std::basic_string<T>& str){ return 4; }
template <class T>
int foo( const std::set< T > & vec ) { return 5; }
template<class C>
bool contains(C const& c, typename C::value_type const& e){
return std::find(begin(c), end(c), e) != std::end(c);
}
template<template<class...> class C, class E, class ... Etc>
auto contains(C<E, Etc...> const& c, E const& e) -> decltype(c.find(e), true) {
return c.find(e) != std::end(c);
}
template<class E, class ... Etc>
auto contains(std::basic_string<E, Etc...> const& c, E const& e) -> bool {
return c.find(e) != std::string::npos;
}
template<class C, class E, class ... Es>
auto contains(C const& s, E const & e, Es...es) -> bool {
return contains(s, e) && contains(s, es...);
}
int main() {
std::map<int, std::string> m {{4,"test"}};
std::vector<int> v;
std::set<int> s {2,4,6,8};
int i{};
std::string str = "abcz";
std::cout << foo(i) << foo(v) << foo(m) << foo(str);
std::cout << contains(v, 4) << contains(m, 4) << contains(s, 2, 4, 6) << contains(str, 'z')
<< contains(str, 'z', 'a');
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8bWFwPgojaW5jbHVkZSA8c2V0PgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KY2xhc3MgaGFzX2ZpbmQgewogICAgdGVtcGxhdGUgPHR5cGVuYW1lIEM+IHN0YXRpYyBzdGQ6OnRydWVfdHlwZSB0ZXN0KCBkZWNsdHlwZSgmQzo6ZmluZCkgKSA7CiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgQz4gc3RhdGljIHN0ZDo6ZmFsc2VfdHlwZSB0ZXN0KC4uLik7CnB1YmxpYzoKCXVzaW5nIHR5cGUgPSBkZWNsdHlwZSh0ZXN0PFQ+KG51bGxwdHIpKTsKICAgIHN0YXRpYyBjb25zdCBib29sIHZhbHVlID0gdHlwZSgpOwp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CmludCBmb28oIGNvbnN0IFQgJiB0ICkgeyByZXR1cm4gMTsgfQoKLy8gb3ZlcmxvYWQgZm9yIHN0ZDo6dmVjdG9yCnRlbXBsYXRlIDxjbGFzcyBUPgppbnQgZm9vKCBjb25zdCBzdGQ6OnZlY3RvcjwgVCA+ICYgdmVjICkgeyByZXR1cm4gMjsgfQoKdGVtcGxhdGUgPGNsYXNzIFQsIGNsYXNzIFU+CmludCBmb28oIGNvbnN0IHN0ZDo6bWFwPCBULCBVID4gJiB2ZWMgKSB7IHJldHVybiAzOyB9Cgp0ZW1wbGF0ZTxjbGFzcyBUPgppbnQgZm9vKGNvbnN0IHN0ZDo6YmFzaWNfc3RyaW5nPFQ+JiBzdHIpeyByZXR1cm4gNDsgfQoKdGVtcGxhdGUgPGNsYXNzIFQ+CmludCBmb28oIGNvbnN0IHN0ZDo6c2V0PCBUID4gJiB2ZWMgKSB7IHJldHVybiA1OyB9Cgp0ZW1wbGF0ZTxjbGFzcyBDPgpib29sIGNvbnRhaW5zKEMgY29uc3QmIGMsIHR5cGVuYW1lIEM6OnZhbHVlX3R5cGUgY29uc3QmIGUpewoJcmV0dXJuIHN0ZDo6ZmluZChiZWdpbihjKSwgZW5kKGMpLCBlKSAhPSBzdGQ6OmVuZChjKTsKfQoKdGVtcGxhdGU8dGVtcGxhdGU8Y2xhc3MuLi4+IGNsYXNzIEMsIGNsYXNzIEUsIGNsYXNzIC4uLiBFdGM+CmF1dG8gY29udGFpbnMoQzxFLCBFdGMuLi4+IGNvbnN0JiBjLCBFIGNvbnN0JiBlKSAtPiBkZWNsdHlwZShjLmZpbmQoZSksIHRydWUpIHsKCXJldHVybiBjLmZpbmQoZSkgIT0gc3RkOjplbmQoYyk7Cn0KCnRlbXBsYXRlPGNsYXNzIEUsIGNsYXNzIC4uLiBFdGM+CmF1dG8gY29udGFpbnMoc3RkOjpiYXNpY19zdHJpbmc8RSwgRXRjLi4uPiBjb25zdCYgYywgRSBjb25zdCYgZSkgLT4gYm9vbCB7CglyZXR1cm4gYy5maW5kKGUpICE9IHN0ZDo6c3RyaW5nOjpucG9zOwp9Cgp0ZW1wbGF0ZTxjbGFzcyBDLCBjbGFzcyBFLCBjbGFzcyAuLi4gRXM+CmF1dG8gY29udGFpbnMoQyBjb25zdCYgcywgRSBjb25zdCAmIGUsIEVzLi4uZXMpIC0+IGJvb2wgewoJcmV0dXJuIGNvbnRhaW5zKHMsIGUpICYmIGNvbnRhaW5zKHMsIGVzLi4uKTsKfQoKaW50IG1haW4oKSB7CglzdGQ6Om1hcDxpbnQsIHN0ZDo6c3RyaW5nPiBtIHt7NCwidGVzdCJ9fTsKCXN0ZDo6dmVjdG9yPGludD4gdjsKCXN0ZDo6c2V0PGludD4gcyB7Miw0LDYsOH07CglpbnQgaXt9OwoJc3RkOjpzdHJpbmcgc3RyID0gImFiY3oiOwoJc3RkOjpjb3V0IDw8IGZvbyhpKSA8PCBmb28odikgPDwgZm9vKG0pIDw8IGZvbyhzdHIpOwoJc3RkOjpjb3V0IDw8IGNvbnRhaW5zKHYsIDQpIDw8IGNvbnRhaW5zKG0sIDQpIDw8IGNvbnRhaW5zKHMsIDIsIDQsIDYpIDw8IGNvbnRhaW5zKHN0ciwgJ3onKQoJPDwgY29udGFpbnMoc3RyLCAneicsICdhJyk7Cn0K