Non-member operator overloading, linker complains

  • Follow


Why does the following code (stripped down to the bare minimum) not  
build?

To be specific, it gives me a linker error like this:
error LNK2019: unresolved external symbol "class Matrix<double,3,3>
__cdecl operator-(class Matrix<double,3,3> const &)"
(??G@YA?AV?$Matrix@N$02$02@@ABV0@@Z) referenced in function _main

The problem seems to be the need to access private members in the
overloaded operator definition and the subsequent friend declaration in
the class. Forward declaring the function outside the class does not
change anything.

Compiler is VC++ 8.0 EE.
To my surprise, it did and does work using VC++ 7.0.

What is the issue and how can I resolve it? Slightly puzzled over this
seemingly simple problem...

Thanks,

Michael

-----------------

#include <iostream>
#include <algorithm>
#include <vector>

template<typename T, unsigned int d, unsigned int e> class Matrix
{
private:
	friend Matrix<T, d, e> operator-( const Matrix<T, d, e>& m );

	typedef std::vector<T> data_type;
	data_type data_;

public:
	Matrix( T value )
	{
		data_.resize( d * e );
		std::fill( data_.begin(), data_.end(), value );
	}

	// ...
};

template <typename T, unsigned int d, unsigned int e>
Matrix<T, d, e> operator-( const Matrix<T, d, e>& m )
{
	Matrix<T, d, e> mRes( m );
	Matrix<T, d, e>::data_type::iterator itrEnd = mRes.data_.end();
	for ( Matrix<T, d, e>::data_type::iterator itr =
	      mRes.data_.begin(); itr != itrEnd; ++itr )
		(*itr) = -(*itr);
	return mRes;
}

template <typename T, unsigned int d, unsigned int e, unsigned int f>
Matrix<T, d, f> operator*( const Matrix<T, d, e>& m1,
                            const Matrix<T, e, f>& m2 )
{
	// does multiplication without accessing
	// private members of Matrix<>
	// ...
	return Matrix<T, d, f>( 0.0 ); // dummy return
}

int main()
{
	Matrix<double, 3, 3> m( 1.0 );
	Matrix<double, 3, 3> n( 2.0 );
	Matrix<double, 3, 3> o = m * n; // no problems
	Matrix<double, 3, 3> p = -n; // yields linker error
	return ( EXIT_SUCCESS );
}


-----------------

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Michael 5/1/2006 3:33:38 PM

Problem is, that U don't specify body of
friend Matrix<T, d, e> operator-( const Matrix<T, d, e>& m ).
Try this code:

template<typename T, unsigned int d, unsigned int e> class Matrix
{
private:
        friend Matrix<T, d, e> operator-( const Matrix<T, d, e>& m ) {
                Matrix<T, d, e> m(1.0);
                return m;
        }

        typedef std::vector<T> data_type;
        data_type data_;

public:
        Matrix( T value )
        {
                data_.resize( d * e );
                std::fill( data_.begin(), data_.end(), value );
        }

        // ...

};


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply malvoj 5/2/2006 10:36:01 AM


Michael Hofmann <mhofmann79@arcor.de> writes:

> #include <iostream>
> #include <algorithm>
> #include <vector>
>
> template<typename T, unsigned int d, unsigned int e> class Matrix
> {
> private:
>       friend Matrix<T, d, e> operator-( const Matrix<T, d, e>& m );

This declares a non-template.


>
>       typedef std::vector<T> data_type;
>       data_type data_;
>
> public:
>       Matrix( T value )
>       {
>               data_.resize( d * e );
>               std::fill( data_.begin(), data_.end(), value );
>       }
>
>       // ...
> };

template<typename T, unsigned int d, unsigned int e> class Matrix;

template<typename T, unsigned int d, unsigned int e>
Matrix<T, d, e> operator-( const Matrix<T, d, e>& m );

template<typename T, unsigned int d, unsigned int e> class Matrix
{
        friend Matrix<T, d, e> operator- <>( const Matrix<T, d, e>& m );
etc.

should help.


> template <typename T, unsigned int d, unsigned int e>
> Matrix<T, d, e> operator-( const Matrix<T, d, e>& m )

This defines a template.

> {
>       Matrix<T, d, e> mRes( m );
>       Matrix<T, d, e>::data_type::iterator itrEnd = mRes.data_.end();
>       for ( Matrix<T, d, e>::data_type::iterator itr =
>             mRes.data_.begin(); itr != itrEnd; ++itr )
>               (*itr) = -(*itr);
>       return mRes;
> }
>
> template <typename T, unsigned int d, unsigned int e, unsigned int f>
> Matrix<T, d, f> operator*( const Matrix<T, d, e>& m1,
>                             const Matrix<T, e, f>& m2 )
> {
>       // does multiplication without accessing
>       // private members of Matrix<>
>       // ...
>       return Matrix<T, d, f>( 0.0 ); // dummy return
> }
>
> int main()
> {
>       Matrix<double, 3, 3> m( 1.0 );
>       Matrix<double, 3, 3> n( 2.0 );
>       Matrix<double, 3, 3> o = m * n; // no problems

Non non-template to be referenced here, so the template specialization
is referenced.


>       Matrix<double, 3, 3> p = -n; // yields linker error

This references the non-template, which hasn't yet be defined.

>       return ( EXIT_SUCCESS );
> }


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Thomas 5/2/2006 10:37:05 AM

Michael Hofmann wrote:

> Forward declaring the function outside the class does not
> change anything.

The trouble is that the friend declaration declares a non-template
function, which overload resolution dutifully selects as the best
match.  But, of course, the non-template operator-() isn't defined
anywhere, hence the link error.

To fix this, you'll need to forward declare the template operator-()
(before the definition of class Matrix) and amend the friend
declaration:

   friend Matrix<T, d, e> operator- <> ( const Matrix<T, d, e>& m );


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply johnchx2 5/2/2006 10:43:12 AM

3 Replies
274 Views

(page loaded in 0.063 seconds)

Similiar Articles:








7/26/2012 3:45:21 PM


Reply: