Lets say I'm rewriting std::min_element
for c 17.
https://en.cppreference.com/w/cpp/algorithm/min_element
I'm unhappy with all the overloads. I'd very much like it if (1) and (3) could be expressed in terms of default arguments.
So (3) could replace (1) with
template< class ForwardIt, class Compare = typename std::less< ??? > >
ForwardIt min_element( ForwardIt first, ForwardIt last, Compare comp = Compare{});
My problem is ??? involves
std::remove_reference<decltype((*first){})>.type
My intent is to have a specialized std::less<MyType>
working for any iterator dereferencing to MyType
and any range using MyType*
.
With the overload it just becomes
template<typename It>
It min_element(It first, It last){
{ auto e = *first;
return min_element(first, last, std::less<decltype(e)>());
}
calling the
template<typename It, typename Comp>
It min_element(It first, It last, Comp c){
{ // it probably needs to be something here, maybe returning an It
}
Is there a concise way to remove the overload with default arguments?
Also I imagine my version to be very buggy.
CodePudding user response:
std::less<void>
does work for any type, because its operator()
is a template and the actual type to be compared is deduced when the operator is called. It was introduced in C 14.
CodePudding user response:
If you have an iterator type, and you want to get what its reference
type is, just ask the traits class: std::iterator_traits<Iterator>::reference
. And since it's a pre-C 20 ForwardIterator, this is required to be a language reference to value_type
. So you can just remove_reference
on it, and you have the type of interest.
C 20 even has a convenient metafunction that does more-or-less the same thing (but it requires C 20-conceptualized iterators): std::iter_reference_t<Iterator>
. Note that since C 20 forward iterators allow proxy iterators (where reference
does not have to be value_type&
), you may need to use iter_value_t<Iterator>
instead.