I am making a class -- a BST -- that can compare templated nodes, which require a comparator, such as std::less
.
the tree is like so :
template<typename T, typename comparator>
class tree
{
private:
comparator compare;
public:
explicit tree (comparator functor);
};
But I can't seem to find which template type I should input in my application.
tree<int> my_bst (std::less<int>);
error: wrong number of template arguments (1, should be 2)
bst::tree<int> my_bst (std::less<int>);
And it makes sense because my template type is incomplete.
How should I profile my constructor?
What is named that property of the templates? Because all I find about that is the sort
page on cppreference.
Typically, I can use sort
like so
std::vector<int> v;
std::sort(v.begin (), v.end (), std::less<>());
How come the specialization of less is deduced? How can I replicate that?
A class template does not need to have a type argument if it has non-type arguments. For example, the following template is a valid class template: Again, these two declarations refer to distinct classes because the values of their non-type arguments differ.
For non-type address arguments, the type of the instance argument must be of the form identifier or & identifier , and the type of the instance argument must match the template parameter exactly, except that a function name is changed to a pointer to function type before matching.
For non-type integral arguments, the instance argument matches the corresponding template parameter as long as the instance argument has a value and sign appropriate to the parameter type.
For example, std::sort compares values two by two to determine which one goes before the other. To perform those comparisons, STL algorithms have a default way of doing it, such as operator< or operator== (depending on whether they use equality or equivalence ).
To save yourself, and everyone else that just wants a default behavior, the extra keystrokes in telling the compiler the type of the comparator you could instead set it by default and then you only have to specify it if you want a different behavior.
template<typename T, typename comparator = std::less<T>>
class tree
{
private:
comparator compare;
public:
explicit tree (comparator functor = comparator{});
};
Will default comparator
to the type std::less<T>
and lets you construct the class like
tree<int> my_bst;
Then, if you want to use a different type, like std::greater
, then you would use
tree<int, std::greater<int>> my_bst;
As you have it right now you would have to use
tree<int, std::less<int>> my_bst(std::less<int>{});
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
| pass an instance of the comparator to the constructor
|
tell the compiler the type of the comparator
to make a tree
using std::less<int>
.
As for why you can do
std::vector<int> v;
std::sort(v.begin (), v.end (), std::less<>());
std::less
has been specialized for std::less<void>
in C++14 and it provides an operator ()
that is templated and will deduce the types passed to it. That means an object of std::less<>
can compare any two types so long as the expression
decltype(std::forward<T>(lhs) < std::forward<U>(rhs))
is valid where both T
and U
are parameter types to the operator ()
.
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