Skip to main content
format more inline code as inline code spans
Source Link

There are several possible improvements to your approach.

First, you can omit the second template parameter by making use of decltype(*std::declval<Iterator>()) What does this mean? So, the std::declval()std::declval<Iterator>() fakes the construction of an Object of type IteratorIterator. The star before it derefences this iterator, which in turn gives us the stored value and the decltype gives us the respective type to this stored value.

Second, you can avoid most of the comparisons changing how your search works. Instead, as already proposed by others, you can write a lower_bound-Function, that gives you the iterator next to val, that is, v<=*it and for every iterator right from it we have v<*it and changing the meaning of the parameter end: this iterator should not be part of the range, resulting in a left-closed-right-open implementation.

Put together a possible implementation could look like the following. I did not test it, but the idea should be clear in case of any misspellings:

template<typename Iterator>
Iterator binarySearch(Iterator begin, Iterator end, const  std::decay_t<decltype(*std::declval<Iterator>())>& v {
        auto diff = end - begin;
        while (diff > 1)
        {
           auto mid = low + diff / 2;
           if (v < *mid)
               end = mid;
           else // v >= *mid
               begin = mid;
           diff = end - begin;
        }
        if (begin == end || *begin < v)
           return end;
        return begin;
}

One could further improve this by making use of right-shift operations, and omitting the setting of the end-iterator in the loop.

There are several possible improvements to your approach.

First, you can omit the second template parameter by making use of decltype(*std::declval<Iterator>()) What does this mean? So, the std::declval() fakes the construction of an Object of type Iterator. The star before derefences this iterator, which in turn gives us the stored value and the decltype gives us the respective type to this stored value.

Second, you can avoid most of the comparisons changing how your search works. Instead, as already proposed by others, you can write a lower_bound-Function, that gives you the iterator next to val, that is, v<=*it and for every iterator right from it we have v<*it and changing the meaning of the parameter end: this iterator should not be part of the range, resulting in a left-closed-right-open implementation.

Put together a possible implementation could look like the following. I did not test it, but the idea should be clear in case of any misspellings:

template<typename Iterator>
Iterator binarySearch(Iterator begin, Iterator end, const  std::decay_t<decltype(*std::declval<Iterator>())>& v {
        auto diff = end - begin;
        while (diff > 1)
        {
           auto mid = low + diff / 2;
           if (v < *mid)
               end = mid;
           else // v >= *mid
               begin = mid;
           diff = end - begin;
        }
        if (begin == end || *begin < v)
           return end;
        return begin;
}

One could further improve this by making use of right-shift operations, and omitting the setting of the end-iterator in the loop.

There are several possible improvements to your approach.

First, you can omit the second template parameter by making use of decltype(*std::declval<Iterator>()) What does this mean? So, the std::declval<Iterator>() fakes the construction of an Object of type Iterator. The star before it derefences this iterator, which in turn gives us the stored value and the decltype gives us the respective type to this stored value.

Second, you can avoid most of the comparisons changing how your search works. Instead, as already proposed by others, you can write a lower_bound-Function, that gives you the iterator next to val, that is, v<=*it and for every iterator right from it we have v<*it and changing the meaning of the parameter end: this iterator should not be part of the range, resulting in a left-closed-right-open implementation.

Put together a possible implementation could look like the following. I did not test it, but the idea should be clear in case of any misspellings:

template<typename Iterator>
Iterator binarySearch(Iterator begin, Iterator end, const  std::decay_t<decltype(*std::declval<Iterator>())>& v {
        auto diff = end - begin;
        while (diff > 1)
        {
           auto mid = low + diff / 2;
           if (v < *mid)
               end = mid;
           else // v >= *mid
               begin = mid;
           diff = end - begin;
        }
        if (begin == end || *begin < v)
           return end;
        return begin;
}

One could further improve this by making use of right-shift operations, and omitting the setting of the end-iterator in the loop.

deleted 12 characters in body
Source Link
Cris Luengo
  • 6.2k
  • 1
  • 13
  • 36

There are several possible improvements to your approach.

First, you can omit the second template parameter by making use of decltype(*std::declval<Iterator>()) What does this mean? So, the std::declval() fakes the construction of an Object of type Iterator. The star before derefences this iterator, which in turn gives us the stored value and the decltype gives us the respective type to this stored value.

Second, you can avoid most of the comparisons changing how your search works. Instead, as already proposed by others, you can write a lower_bound-Function, that gives you the iterator next to val, that is, v<=*it and for every iterator right from it we have v<*it and changing the meaning of the parameter end: this iterator should not be part of the range, resulting in a left-closed-right-open implementation.

Put together a possible implementation could look like the following. I did not test it, but the idea should be clear in case of any misspellings:

template<typename Iterator, typename T>Iterator>
Iterator binarySearch(Iterator begin, Iterator end, const  std::decay_t<decltype(*std::declval<Iterator>())>& v {
        auto diff = end - begin;
        while (diff > 1)
        {
           auto mid = low + diff / 2;
           if (v < *mid)
               end = mid;
           else // v >= *mid
               begin = mid;
           diff = end - begin;
        }
        if (begin == end || *begin < v)
           return end;
        return begin;
}

One could further improve this by making use of right-shift operations, and omitting the setting of the end-iterator in the loop.

There are several possible improvements to your approach.

First, you can omit the second template parameter by making use of decltype(*std::declval<Iterator>()) What does this mean? So, the std::declval() fakes the construction of an Object of type Iterator. The star before derefences this iterator, which in turn gives us the stored value and the decltype gives us the respective type to this stored value.

Second, you can avoid most of the comparisons changing how your search works. Instead, as already proposed by others, you can write a lower_bound-Function, that gives you the iterator next to val, that is, v<=*it and for every iterator right from it we have v<*it and changing the meaning of the parameter end: this iterator should not be part of the range, resulting in a left-closed-right-open implementation.

Put together a possible implementation could look like the following. I did not test it, but the idea should be clear in case of any misspellings:

template<typename Iterator, typename T>
Iterator binarySearch(Iterator begin, Iterator end, const  std::decay_t<decltype(*std::declval<Iterator>())>& v {
        auto diff = end - begin;
        while (diff > 1)
        {
           auto mid = low + diff / 2;
           if (v < *mid)
               end = mid;
           else // v >= *mid
               begin = mid;
           diff = end - begin;
        }
        if (begin == end || *begin < v)
           return end;
        return begin;
}

One could further improve this by making use of right-shift operations, and omitting the setting of the end-iterator in the loop.

There are several possible improvements to your approach.

First, you can omit the second template parameter by making use of decltype(*std::declval<Iterator>()) What does this mean? So, the std::declval() fakes the construction of an Object of type Iterator. The star before derefences this iterator, which in turn gives us the stored value and the decltype gives us the respective type to this stored value.

Second, you can avoid most of the comparisons changing how your search works. Instead, as already proposed by others, you can write a lower_bound-Function, that gives you the iterator next to val, that is, v<=*it and for every iterator right from it we have v<*it and changing the meaning of the parameter end: this iterator should not be part of the range, resulting in a left-closed-right-open implementation.

Put together a possible implementation could look like the following. I did not test it, but the idea should be clear in case of any misspellings:

template<typename Iterator>
Iterator binarySearch(Iterator begin, Iterator end, const  std::decay_t<decltype(*std::declval<Iterator>())>& v {
        auto diff = end - begin;
        while (diff > 1)
        {
           auto mid = low + diff / 2;
           if (v < *mid)
               end = mid;
           else // v >= *mid
               begin = mid;
           diff = end - begin;
        }
        if (begin == end || *begin < v)
           return end;
        return begin;
}

One could further improve this by making use of right-shift operations, and omitting the setting of the end-iterator in the loop.

Source Link

There are several possible improvements to your approach.

First, you can omit the second template parameter by making use of decltype(*std::declval<Iterator>()) What does this mean? So, the std::declval() fakes the construction of an Object of type Iterator. The star before derefences this iterator, which in turn gives us the stored value and the decltype gives us the respective type to this stored value.

Second, you can avoid most of the comparisons changing how your search works. Instead, as already proposed by others, you can write a lower_bound-Function, that gives you the iterator next to val, that is, v<=*it and for every iterator right from it we have v<*it and changing the meaning of the parameter end: this iterator should not be part of the range, resulting in a left-closed-right-open implementation.

Put together a possible implementation could look like the following. I did not test it, but the idea should be clear in case of any misspellings:

template<typename Iterator, typename T>
Iterator binarySearch(Iterator begin, Iterator end, const  std::decay_t<decltype(*std::declval<Iterator>())>& v {
        auto diff = end - begin;
        while (diff > 1)
        {
           auto mid = low + diff / 2;
           if (v < *mid)
               end = mid;
           else // v >= *mid
               begin = mid;
           diff = end - begin;
        }
        if (begin == end || *begin < v)
           return end;
        return begin;
}

One could further improve this by making use of right-shift operations, and omitting the setting of the end-iterator in the loop.