I'm trying to create a matrix class. This class has a nested class called linear_t (which represents both columns and rows) and linear_t has another nested class called iterator_t.
////////////////////////////////////////////////////////
template <typename T>
class matrix_t
{
public:
// ...
class linear_t;
typedef linear_t row_t;
typedef linear_t col_t;
};
////////////////////////////////////////////////////////
template <typename T>
class matrix_t<T>::linear_t
{
public:
// ...
class iterator_t;
};
////////////////////////////////////////////////////////
template <typename T>
class matrix_t<T>::linear_t::iterator_t
{
public:
// ...
};
////////////////////////////////////////////////////////
template <typename T>
inlinebooloperator!= (
typename matrix_t<T>::linear_t::iterator_t& it_i,
typename matrix_t<T>::linear_t::iterator_t& it_j
)
{
returntrue; // just to allow compiling
}
I get a compilation error when I try to use the operator!= from the main function. It seems the compiler cannot find the implementation, but I don't understand the reason.
Here is the error:
main.cpp: In function `int main(int, char**)':
main.cpp:10: error: no match for 'operator!=' in 'it_1 != it_2'
And here is the fragment of code where the operator is invoked:
1 2 3 4 5 6 7 8
matrix_t<double> m;
matrix_t<double>::row_t r;
matrix_t<double>::row_t::iterator_t it_1, it_2;
if (it_1 != it_2)
{
// ...
}
I don't understand what is the problem. Any help or suggestion will be more than welcomed.
That is very strange. I have the same problem over here.
I can get around it by making the operator overload part of the iterator class rather than a global function (which is my preferred style). So I guess this is a solution:
First of all, thanks to all of you for your replies.
jsmith, I'm using g++ 3.4.5. But the initial problem is not the friend declaration. The original problem is that the compiler cannot find the implementation of the operator!= () if I declare it as a global function (not as a member function) as I commented in the first post.
Sorry for my insistence but I think there is something else. For example, when using the STL, we usually do things like this:
map<char,int>::iterator it;
I think inheritance could be a possible solution (I don know if it is used in the STL) but we could do something like this (please, read the first post to understand the following fragment of code):
1 2 3 4 5 6 7 8 9 10 11
template <typename T>
class base_iterator_t
{
// ...
};
template <typename T>
class matrix_t<T>::linear_t::iterator_t : public base_iterator_t<T>
{
// ...
};
This solution presents two disadvantages:
1. inheritance implies less performance
2. each function requires two versions (see the following example for the operator!= method)
In regard to the original problem:
Here is an extract from the book "C++ templates the complete guide" concerning template argument deduction:
Complex type declarations are built from more elementary constructs (pointer, reference, array, and function declarators; pointer-to-member declarators; template-ids; and so forth), and the matching process proceeds from the top-level construct and recurses through the composing elements. It is fair to say that most type declaration constructs can be matched in this way, and these are called deduced contexts. However, a few constructs are not deduced contexts:
Qualified type names. A type name like Q<T>::X will never be used to deduce a template parameter T, for example.