One of the places I hoped I would be able to use the new template argument deduction, was in construction of std::set
's / std::map
s / any other containers with custom comparators - my goal is to create a one-line statement, that will create an efficient set with a lambda comparator.
What I can do since C++11 is:
std::set<int, std::function<bool(int, int)>> s([](int a, int b) {return a > b;});
But since it uses std::function
, it is noticeably slower.
Another option is:
auto mycomp = [](int a, int b) {return a > b; };
std::set<int, decltype(mycomp)> s(mycomp);
It gets the job done, but 1) It requires 2 lines, and creation of the mycomp
variable 2) I need to pass mycomp
's type explicitly.
As I read on reference pages, none of the standard containers has a deduction guide for this kind of situation. Unfortunately, I'm afraid it cannot be even done with the current language standard (C++17), as one can find:
Class template argument deduction is only performed if no template argument list is present. If a template argument list is specified, deduction does not take place.
What is the reasoning behind this? Why didn't they allow partial argument deduction? I guess there are some problems with it that I overlook, but in my opinion it would be more than helpful.
In one line (C++17)
std::set s(std::initializer_list<int>{}, [](int a, int b) {return a > b; });
As alternative, you can still make the old make_xxx
template <typename T, typename COMP>
std::set<T, COMP> make_set(COMP comp)
{
return std::set<T, COMP>{comp};
}
auto s = make_set<int>([](int a, int b) {return a > b; });
What you should be doing is writing a comparator functor type, so you don't need to proxy to it when using your set. It will be a lot more lines of code (the atrocity!), but is better in virtually every way:
struct MyComparator
{
bool operator()(int a, int b) const { ...; }
};
using MySet = std::set<int, MyComparator>;
And from then on, you'd just create your customly sorted set where you need it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With