By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,079 Members | 901 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,079 IT Pros & Developers. It's quick & easy.

Link problem with template in Visual C++ 2005 Express

P: 8
I have a template for a three dimensional array that I have been working on using Visual C++ 6.0. Under version 6 this code worked fine. However, last night I downloaded Visual C++ 2005 Express and and trying to get the same code to work. Under Visual C++ 2005 I am seeing linker errors. The problem is in the definition of a couple of friend operators that the linker does not like for some reason. I am assuming I have a mistake in my definitions and that Visual C++ 2005 is just pickier about it than the old vers. 6 was. I just can not seem to find the issue.

My template definition is,

Expand|Select|Wrap|Line Numbers
  1. template <class type>
  2. class Array
  3. {
  4.     private:
  5.         type* data;
  6.         unsigned int iMax;
  7.         unsigned int jMax;
  8.         unsigned int kMax;
  9.  
  10.     public:
  11.         Array()
  12.         {
  13.             data = 0;
  14.         }
  15.  
  16.         Array(const Array<type>& _obj)
  17.         {
  18.             iMax = _obj.iMax;
  19.             jMax = _obj.jMax;
  20.             kMax = _obj.kMax;
  21.  
  22.             data = new type[iMax * jMax * kMax];
  23.             for (unsigned int ijk = 0; ijk < iMax * jMax * kMax; ijk++)
  24.             {
  25.                 data[ijk] = _obj.data[ijk];
  26.             }
  27.         }
  28.  
  29.         Array(const unsigned int _iMax, const unsigned int _jMax, const unsigned int _kMax)
  30.         {
  31.             iMax = _iMax;
  32.             jMax = _jMax;
  33.             kMax = _kMax;
  34.  
  35.             data = new type[iMax * jMax * kMax];
  36.         }
  37.  
  38.         ~Array()
  39.         {
  40.             if (data != 0)
  41.             {
  42.                 delete [] data;
  43.                 data = 0;
  44.             }
  45.         }
  46.  
  47.         Array<type>& operator=(const Array<type>& rhs)
  48.         {
  49.             if (&rhs != this)
  50.             {
  51.  
  52.                 iMax = rhs.iMax;
  53.                 jMax = rhs.jMax;
  54.                 kMax = rhs.kMax;
  55.  
  56.                 if (data!= 0)
  57.                 {
  58.                     delete [] data;
  59.                 }
  60.  
  61.                 data = new type[iMax * jMax * kMax];
  62.                 for (unsigned int ijk = 0; ijk < iMax * jMax * kMax; ijk++)
  63.                 {
  64.                     data[ijk] = rhs.data[ijk];
  65.                 }
  66.             }
  67.  
  68.             return *this;
  69.         }
  70.  
  71.         Array<type>& operator=(const type& rhs)
  72.         {
  73.             for (unsigned int ijk = 0; ijk < iMax * jMax * kMax; ijk++)
  74.             {
  75.                 data[ijk] = rhs;
  76.             }
  77.  
  78.             return *this;
  79.         }
  80.  
  81.         friend Array<type> operator+(const type& lhs, const Array<type>& rhs);
  82.         friend Array<type> operator-(const type& lhs, const Array<type>& rhs);
  83. };
  84.  
  85. template <class type>
  86. Array<type> operator+(const type& lhs, const Array<type>& rhs)
  87. {
  88.     Array<type> newMat(rhs);
  89.  
  90.     for (unsigned int ijk = 0; ijk < newMat.iMax * newMat.jMax * newMat.kMax; ijk++)
  91.     {
  92.         newMat.data[ijk] += lhs;
  93.     }
  94.  
  95.     return newMat;
  96. }
  97.  
  98. template <class type>
  99. Array<type> operator-(const type& lhs, const Array<type>& rhs)
  100. {
  101.     Array<type> newMat(rhs);
  102.  
  103.     for (unsigned int ijk = 0; ijk < newMat.iMax * newMat.jMax * newMat.kMax; ijk++)
  104.     {
  105.         newMat.data[ijk] = lhs - newMat.data[ijk];
  106.     }
  107.  
  108.     return newMat;
  109. }
  110.  
and I am calling the operators from a simple test routing,

Expand|Select|Wrap|Line Numbers
  1. #include "Array.h"
  2.  
  3. int main(int argc, char* argv[])
  4. {
  5.     Array<int> a0_t4(3, 3, 1);
  6.     a0_t4 = 2;
  7.     Array<int> a2_t4;
  8.     a2_t4 = 1 + a0_t4;
  9.     a2_t4 = 1 - a0_t4;
  10.  
  11.     return 0;
  12. }
  13.  
The errors I am getting from the linker are,

Error 1 error LNK2019: unresolved external symbol "class Array<int> __cdecl operator-(int const &,class Array<int> const &)" (??G@YA?AV?$Array@H@@ABHABV0@@Z) referenced in function _main TestFlow.obj
Error 2 error LNK2019: unresolved external symbol "class Array<int> __cdecl operator+(int const &,class Array<int> const &)" (??H@YA?AV?$Array@H@@ABHABV0@@Z) referenced in function _main TestFlow.obj
Error 3 fatal error LNK1120: 2 unresolved externals C:\Documents and Settings\sstanley\Desktop\cppPlaying\TestFlow\Debu g\TestFlow.exe


Can anyone tell me what I am doing wrong in these operators?
Sep 15 '07 #1
Share this Question
Share on Google+
5 Replies


P: 8
My apologies. I seem to have posted this under articles by accident. I will repost under forums.
Sep 15 '07 #2

Expert 10K+
P: 11,448
My apologies. I seem to have posted this under articles by accident. I will repost under forums.
I'll move your thread to the C/C++ Forum section for you; no problem.

kind regards,

Jos
Sep 15 '07 #3

weaknessforcats
Expert Mod 5K+
P: 9,197
This has to do with bound vs unbound friend function templates.

That is, if you have an Array<int> your friend declatation must be Array<int> and not Array<type>. This is ean example of a bound friend template. Only Array<int> has the operator+ defined.

If you want an operator+ created for all Array<type>, then the friend function must be defined inside the class defintion.

Here is your code in a working condition as far as compile and link goes:
Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. template <class type>
  5. class Array
  6. {
  7.     private:
  8.         type* data;
  9.         unsigned int iMax;
  10.         unsigned int jMax;
  11.         unsigned int kMax;
  12.  
  13.     public:
  14.         Array()
  15.         {
  16.             data = 0;
  17.         }
  18.  
  19.         Array(const Array<type>& _obj)
  20.         {
  21.             iMax = _obj.iMax;
  22.             jMax = _obj.jMax;
  23.             kMax = _obj.kMax;
  24.  
  25.             data = new type[iMax * jMax * kMax];
  26.             for (unsigned int ijk = 0; ijk < iMax * jMax * kMax; ijk++)
  27.             {
  28.                 data[ijk] = _obj.data[ijk];
  29.             }
  30.         }
  31.  
  32.         Array(const unsigned int _iMax, const unsigned int _jMax, const unsigned int _kMax)
  33.         {
  34.             iMax = _iMax;
  35.             jMax = _jMax;
  36.             kMax = _kMax;
  37.  
  38.             data = new type[iMax * jMax * kMax];
  39.         }
  40.  
  41.         ~Array()
  42.         {
  43.             if (data != 0)
  44.             {
  45.                 delete [] data;
  46.                 data = 0;
  47.             }
  48.         }
  49.  
  50.         Array<type>& operator=(const Array<type>& rhs)
  51.         {
  52.             if (&rhs != this)
  53.             {
  54.  
  55.                 iMax = rhs.iMax;
  56.                 jMax = rhs.jMax;
  57.                 kMax = rhs.kMax;
  58.  
  59.                 if (data!= 0)
  60.                 {
  61.                     delete [] data;
  62.                 }
  63.  
  64.                 data = new type[iMax * jMax * kMax];
  65.                 for (unsigned int ijk = 0; ijk < iMax * jMax * kMax; ijk++)
  66.                 {
  67.                     data[ijk] = rhs.data[ijk];
  68.                 }
  69.             }
  70.  
  71.             return *this;
  72.         }
  73.  
  74.         Array<type>& operator=(const type& rhs)
  75.         {
  76.             for (unsigned int ijk = 0; ijk < iMax * jMax * kMax; ijk++)
  77.             {
  78.                 data[ijk] = rhs;
  79.             }
  80.  
  81.             return *this;
  82.         }
  83.  
  84.        // bound
  85.         friend Array<int> operator+(int lhs, Array<int> rhs);
  86.        //unbound
  87.         friend Array<type> operator-(const type& lhs, const Array<type>& rhs)
  88.         {
  89.              Array<type> newMat(rhs);
  90.  
  91.               for (unsigned int ijk = 0; ijk < newMat.iMax * newMat.jMax * newMat.kMax; ijk++)
  92.               {
  93.                  newMat.data[ijk] = lhs - newMat.data[ijk];
  94.               }
  95.  
  96.           return newMat;
  97.         }
  98. };
  99.  
  100. //template <class type>
  101. //Array<type> operator+(const type lhs&, const Array<type>& rhs)
  102. Array<int> operator+(int lhs, Array<int> rhs)
  103. {
  104.     Array<int> newMat(rhs);
  105.  
  106.     for (unsigned int ijk = 0; ijk < newMat.iMax * newMat.jMax * newMat.kMax; ijk++)
  107.     {
  108.         newMat.data[ijk] += lhs;
  109.     }
  110.  
  111.     return newMat;
  112. }
  113.  
  114. template <class type>
  115. Array<type> operator-(const type& lhs, const Array<type>& rhs)
  116. {
  117.     Array<type> newMat(rhs);
  118.  
  119.     for (unsigned int ijk = 0; ijk < newMat.iMax * newMat.jMax * newMat.kMax; ijk++)
  120.     {
  121.         newMat.data[ijk] = lhs - newMat.data[ijk];
  122.     }
  123.  
  124.     return newMat;
  125. }
  126.  
  127.  
  128. //and I am calling the operators from a simple test routing,
  129.  
  130.  
  131. //Code: ( text )
  132. //#include "Array.h"
  133.  
  134. int main(int argc, char* argv[])
  135. {
  136.     Array<int> a0_t4(3, 3, 1);
  137.     a0_t4 = 2;
  138.     Array<int> a2_t4;
  139.  
  140.     a2_t4 = 1 + a0_t4;
  141.     a2_t4 = 1 - a0_t4;
  142.  
  143.     return 0;
  144. }
  145.  
Sep 16 '07 #4

P: 8
If you want an operator+ created for all Array<type>, then the friend function must be defined inside the class definition.
Interesting. So, declaring the friend function inside of the class definition template is not enough. The actual function must be defined inside of the class template.

Thanks for the help.
Sep 17 '07 #5

weaknessforcats
Expert Mod 5K+
P: 9,197
So, declaring the friend function inside of the class definition template is not enough. The actual function must be defined inside of the class template.
This is due to how templates work. You can't use a function prototype as a template. The compiler is not able to seek out the template specializations. So, you either specialize the template yourself and put the function prototype of the specialized template in the class (bound) or you have to put the entire friend template in the class (unbound).

When export templates are finally used, this restriction will go away. Currently, I don't know a a compiler that supports export templates.
Sep 17 '07 #6

Post your reply

Sign in to post your reply or Sign up for a free account.