I have a Matrix class that derives from an Eigen template:
template<typename T,
int _Rows = Eigen::Dynamic,
int _Cols = Eigen::Dynamic>
class Matrix : public Eigen::Matrix<T, _Rows, _Cols>
I need to use this type as a key for an std::map
container, hence I need a comparator object. I would like to specialize std::less
for this purpose. A draft version that does not compile looks like this, to get you the idea:
template<typename Matrix<typename T,
int _Rows = Eigen::Dynamic,
int _Cols = Eigen::Dynamic> > >
struct less
{
bool operator()(const Matrix<T,
Rows,
Cols>& lhs,
const Matrix<T,
Rows,
Cols>& rhs) const;
{
Matrix<T,
Rows,
Cols>::const_iterator lhsIt = lhs.begin();
Matrix<T,
Rows,
Cols>::const_iterator rhsIt = rhs.begin();
for (;
lhsIt != lhs.end();
++lhsIt, ++rhsIt)
{
if (*lhsIt < *rhsIt)
{
return true;
}
}
return false;
}
};
The problem is that I want to specialize std::less
using a template. What is a correct way to code this ? Do I have to resort to template specialization ?
I will also need to specialize std::hash
in a similar way to be able to use std::map
.
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.
Template in C++is a feature. We write code once and use it for any data type including user defined data types. For example, sort() can be written and used to sort any data type items. A class stack can be created that can be used as a stack of any data type.
A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)
There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.
The problem is that I want to specialize
std::less
using a template.
Don't. std::less
means "call the <
operator" for this class"; specializing it for a class with no <
operator is needlessly confusing to others reading your code, and specializing it for a class with a <
operator is pointless.
Just implement a correct operator<
overload, and you can use it in std::map
.
I will also need to specialize
std::hash
in a similar way to be able to usestd::map
.
No, you don't. That's only needed for unordered_map
.
By the way, your comparison algorithm is wrong. It reports [2, 1] < [1, 2]
and [1, 2] < [2, 1]
. Not to mention that it doesn't handle the case when the two matrices have different numbers of elements.
The correct syntax is
template <typename T, int Row, int Col>
struct less<Matrix<T, Row, Col>>
{
bool operator()(const Matrix<T, Row, Col>& lhs,
const Matrix<T, Row, Col>& rhs) const
{
// implementation:
return lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
};
which is a specialization.
BTW, your implementation doesn't respect less requirement: (it is not symmetric).
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