Salama
Salama

Reputation: 46

overloadded method on a class template, always gives unable to match function definition to declaration

I'm somehow new to templates and I'm trying to modify some library that provide matrix and vector operation to c++, i have a vector class which I'm trying to overload the operator() for it to handle an operation like this Vector(2:5) will return a vector that has elements 2,3,4,5 of the original vector, and I'm using a class called colon where colon(2:5) will represent the (2:5) effect as i found that c++ has no operator: . hope i gave a proper introduction. The relevant code is as follows

The Vector Class

template< size_t M, typename T = float >
class Vector
{
public:
typedef T   value_type;
Vector operator-( const Vector& other ) const;
template <size_t N, typename T> Vector<N,T> operator()(const  colon &cex) const;
.
.
}

and the corresponding implementation

template< size_t M, typename T >
template< size_t N,T>
Vector<N,T>
Vector<M,T>::operator()( const colon &cex ) const
{
long i, ii, st = 0, in = 0, en = 0, s;
cex.apply(M, st, in, en, s);
if (s && (st>0) && (st>M))
{
Vector<N,T> result;
for (i=st,ii=0;i+=in,ii++;i<=en,ii<N)
{
result(ii)=array(i);
return result;
}

}
return 0;
}

the return 0 here is just a place holder, it should return an empty vector. the colon class (which is taken from another library and modified by me).

class colon
{
public:
/// Colon expression '(:)'
colon() { _flag = 'a'; }
/// Colon expression of type '(2:5)'
colon(long s, long e) { _s = s; _i = 1; _e = e; _flag = 'r'; }
void apply(long s, long &f, long &i, long &l, long &n) const;

private:
/// Type of colon expression.
char _flag;
/// First index.
long _s;
/// Increment.
long _i;
/// Last index.
long _e;

}; /* class colon */

and the relevant implementation is

void
colon::apply(long n, long &st, long &in, long &en,
     long &le) const
{
switch (_flag)
{
    case 'r':
        if ((_i == 0 ) || ((_e - _s) / _i < 0 )) le = 0;
        else
        {
            st = _s;
            in = _i;
            en = _e - (_e - _s) % _i;
            le = (_e - _s) / _i + 1;
        }
        break;
    case 'a':
        if (n)
        {
            st = 1;
            in = 1;
            en = n;
            le = n;
        }
        else le = 0;
        break;

 }
}

when compiling this code i always receive the error

Error 1 error C2244: 'Vector::operator ()' : unable to match function definition to an existing declaration

and the output of the compiler is

error C2244: 'Vector<M,T>::operator ()' : unable to match function 
definition to an existing declaration

definition
'Vector<N,T> Vector<M,T>::operator ()(const colon &) const'

existing declarations
'Vector<N,T> Vector<M,T>::operator ()(const colon &) const'

So What I'm doing wrong here?

Upvotes: 1

Views: 332

Answers (2)

Rost
Rost

Reputation: 9089

First problem is that you write template function arguments wrong: template<size_t N,T>. It shall be template<size_t N, typename T>, otherwise it will be considered as non-type template parameter (some specific value of T).

Second problem is that function template parameter name T is ambiguos. Compiler could not know which T it shall use, from class template parameter or from function one? Remember, function and class template parameters are unrelated. So you need to rename it:

template<size_t M, typename T> class Vector
{
public:

template <size_t N, typename X> Vector<N,X> operator()() const;
};

template<size_t M, typename T>
template<size_t N, typename X> Vector<N,X> Vector<M,T>::operator()() const
{ 
}

But actually if you don't need cross-type operations and X will be always the same type as T you could just skip it in function and parametrize it only by size:

template<size_t M, typename T> class Vector
{
public:

template <size_t N> Vector<N,T> operator()() const;
};

template<size_t M, typename T>
template<size_t N> Vector<N,T> Vector<M,T>::operator()() const
{ 
}

Upvotes: 1

In your declaration you write:

template< size_t M, typename T = float >
class Vector
{
template <size_t N, typename T> 
Vector<N,T> operator()(const  colon &cex) const

and in your definition you write:

template< size_t M, typename T >
template< size_t N,T>
Vector<N,T>
Vector<M,T>::operator()( const colon &cex ) const

Notice the difference in the second template line:

template <size_t N, typename T> 

vs.

template< size_t N,T>

You are missing the typename there. So instead of passing a type to T you expect to get passed an instance of T (which is only possible if T is an integral type).

This shows that your declaration and definition do in fact differ and where the error originates from.

As your second T would hide the first (which is not allowed - see comments), I think you either want to rename the second Tand add the typename in the definition or you want to remove the second T altogether.

Upvotes: 1

Related Questions