1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <type_traits>
template< class T >
class has_find
{
class yes { char c; };
class no { yes c[2]; };
struct mixin
{
void find( void );
};
// Calling derived::find is only non-ambiguous if
// T::find does not exist, cf. 10.2.2.
template< class U> struct derived : public U, public mixin {};
// The following template will help on deduction based on this fact.
// If U is type void (mixin::*) (void) then the template can be
// instantiated with u = &derived< U >::find if and only if T::find
// does not exist.
template< class U, U u >
class binder {};
// Therefore, the following template function is only selected if there
// is no T::find:
template< class U >
static no deduce( U, binder< void (mixin::*) (void), &derived< U >::find >* = 0 );
// Selected otherwise.
static yes deduce( ... );
// Provides an T object:
static T T_obj( void );
public:
static const bool result = ( sizeof( yes ) == sizeof( deduce( T_obj() ) ) );
typedef typename std::conditional<result, std::true_type, std::false_type>::type type;
};
template <typename C, typename V>
typename C::const_iterator find(const C& c, const V& val)
{
return detail::find_with_member_function(c, val, has_find<C>::type());
}
namespace detail
{
template <typename C, typename V>
typename C::const_iterator find_with_member_function(const C& c, const V& val, const std::true_type&)
{
std::cout << "call find member function\n";
return c.find(val);
}
template <typename C, typename V>
typename C::const_iterator find_with_member_function(const C& c, const V& val, const std::false_type&)
{
std::cout << "call std::find\n";
return std::find(c.begin(), c.end(), val);
}
}
int main()
{
std::vector<int> v;
v.push_back(4);
find(v, 4);
std::map<int, std::string> m;
m[0] = "0";
find(m, 0);
return 0;
} |
Partager