template<typename T, typename Iterator>
Iterator FindImpl(const T& v, Iterator first, Iterator last, 
    std::bidirectional_iterator_tag) {
    while (first != last) {
        if (*first == v)
            return first;
        first++;
    }
    return last;
}

template<typename T, typename Iterator>
Iterator FindImpl(const T& v, Iterator first, Iterator last,
    std::random_access_iterator_tag) {
    Iterator end = last;
    while (first != end) {
        Iterator middle = first + ((end - first) / 2);
        if (*middle < v)
            first = middle + 1;
        else
            end = middle;
    }
    if (*last == v)
        return end;
    return last;
}

template<typename T, typename Iterator>
Iterator Find(const T& value, Iterator first, Iterator last) {
    typedef typename std::iterator_traits<Iterator>::iterator_category category;
    return FindImpl(value, first, last, category());
}