The bidirectional iterators have no luxuries like random access iterators, and hence need to depend upon the std::next
and std::prev
, when someone needs to do operations like
std::set<int> s{ 1, 2, 3, 4, 5 };
//std::set<int> s2(s.cbegin(), s.cbegin() + 2); // won't work as there is no operator+ for std::set::const_iterator
std::set<int> s2(s.cbegin(), std::next(s.cbegin(), 2));
//std::set<int> s3(s.cbegin(), s.cend() - 2); // won't work as there is no operator- for std::set::const_iterator
std::set<int> s3(s.cbegin(), std::prev(s.cend(), 2));
However, we can implement those operator+
and operator-
using the above std::next
and std::prev
.
#include <set>
#include <iterator> // std::iterator_traits, std::next, std::prev
template<typename InputIt>
constexpr InputIt operator+(InputIt it,
typename std::iterator_traits<InputIt>::difference_type n)
{
return std::next(it, n);
}
template<typename InputIt>
constexpr InputIt operator-(InputIt it,
typename std::iterator_traits<InputIt>::difference_type n)
{
return std::prev(it, n);
}
int main()
{
std::set<int> s{ 1, 2, 3, 4, 5 };
std::set<int> s2(s.cbegin(), s.cbegin() + 2); // works now
std::set<int> s3(s.cbegin(), s.cend() - 2); // works now
}
- Are there any downsides of using those implementations?
- If not, isn't nice to have in the C++ standard library?
Update:
Using InputIt
would be a mistake as @Nicol Bolas mentioned in his answer. I thought to demonstrate the idea though. Anyways, let us consider a SFINE ed solution instead, which accepts only the bidirectional iterator. Would be there any other problems, other than what Nicol mentioned?
#include <type_traits>
#include <iterator> // std::iterator_traits, std::bidirectional_iterator_tag, std::next, std::prev
template<typename BidirIterators>
constexpr auto operator+(BidirIterators it,
typename std::iterator_traits<BidirIterators>::difference_type n)
-> std::enable_if_t<
std::is_same_v<
std::bidirectional_iterator_tag,
typename std::iterator_traits<BidirIterators>::iterator_category
>, BidirIterators
>
{
return std::next(it, n);
}
template<typename BidirIterators>
constexpr auto operator-(BidirIterators it,
typename std::iterator_traits<BidirIterators>::difference_type n)
-> std::enable_if_t<
std::is_same_v<
std::bidirectional_iterator_tag,
typename std::iterator_traits<BidirIterators>::iterator_category
>, BidirIterators
>
{
return std::prev(it, n);
}