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 != last) {
        Iterator middle = first + ((last - first) / 2);
        if (*middle < v) {
            first = middle + 1;
        } else {
            last = middle;
        }
    }
    if (*last == v) return last;
    return end;
}

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());
}