Reputation:
Hey, I'm getting a linker error LNK2019: unresolved external symbol when trying to use an overloaded + operator. I'll show you snip-its from the class, and how I'm using it in main. If you need to see more, let me know, I'm just going to try and keep things concise.
/** vec.h **/
#ifndef __VEC_H_
#define __VEC_H_
#include <iostream>
#include <vector>
namespace xoor{
template<typename T>
class vec{
public:
inline friend vec<T> operator + (const vec<T>&, const vec<T>&);
inline const vec<T>& operator += (const vec<T>&);
private:
std::vector<T> m_index;
}; // Vec.
template<typename T>
vec<T>& operator + (const vec<T>& a, const vec<T>& b){
vec<T> product = a;
product += b;
return product;
} // Addition.
template<typename T>
const vec<T>& vec<T>::operator += (const vec<T>& v){
for (unsigned short i =0; i < m_index.size(); ++i){
if (i >= v.size())
break;
m_index[i] += v.getIndex()[i];
}
return * this;
} // Addition Compound.
} // xoor
#endif // __VEC_H_
Note that I've got [] overloaded as well, so I'm just accessing parts of m_index with it. getIndex() just returns m_index. And size() returns m_index.size()
/** main.cpp **/
#include <iostream>
#include "vec.h"
void testHook();
int main(){
testHook();
system("PAUSE");
return 0;
}
void testHook(){
using namespace xoor;
vec<double> vA(3); // passing 3 for 3 elements
vec<double> vB(3);
// v + v
std::cout << "\n\tA + B = ";
vec<double> vAB(3);
vAB = vA + vB; // PRODUCES THE LNK2019
vAB.print(std::cout); // Outputs the vec class to the console.
}
Error Message:
Error 1 error LNK2019: unresolved external symbol "class xoor::vec<double> __cdecl xoor::operator+(class xoor::vec<double> const &,class xoor::vec<double> const &)" (??Hxoor@@YA?AV?$vec@N@0@ABV10@0@Z) referenced in function "void __cdecl testHook(void)" (?testHook@@YAXXZ) main.obj
Update:
The following is now directly above the class definition. I continue to get the same linker error, as described above.
template<typename T>
class vec;
template<typename T>
vec<T> operator + (const vec<T>&, const vec<T>&);
Update 2: Solution.
The above update is incorrect. sbi's solution did work, I just failed to template the operator as follows.
template<typename T>
vec<T> operator +<T> (const vec<T>&, const vec<T>&);
sbi, and david were discussing why I was using friends in the first place. Initially I was using them, because you can not pass two parameters to an overloaded binary operator such as +, and immediate sought after friends as the solution. As it turns out, you can still use the binary operator quite easily with a single parameter. Here is the final solution.
// ...
template<typename T>
class vec{
public:
const vec<T> operator + (const vec<T>&, const vec<T>&)const;
// ...
}; // Vec.
template<typename T>
const vec<T> vec<T>::operator + (const vec<T>& v)const{
matrix<T> product = *this;
vec(product += v);
} // Addition.
Also, for anyone else reading this, its worth while to check out sbi's notes at the bottom of his answer. There are some things I've been doing that are superfluous.
Thanks for the help everyone. Happy coding.
Upvotes: 5
Views: 11162
Reputation: 224089
In order to befriend a template, I think you'll need to declare that template before the class definition in which you want to befriend it. However, for this declaration to compile, you'll need to forward-declare the class template. So this should work:
template<typename T>
class vec;
template<typename T>
vec<T> operator + (vec<T>, const vec<T>&);
template<typename T>
class vec{
public:
friend vec<T> operator +<T> (vec<T>, const vec<T>&);
// ...
This befriends a specific instance of the operator+()
function template, namely operator+<T>
. (You can also befriend all instances of a template:
// no forward declarations necessary
template<typename T>
class some_class {
template<typename U>
friend void f(vec<U>&);
// ...
};
However, that's less often useful than the other one.)
Edit: A comment by David got me thinking (should've done this from the beginning!) and that lead to the discovery that the friend
declaration is unnecessary. Your operator+
is only using one public
member function of vec
(operator+=
) and thus doesn't need to be a friend
of the class. So the above would simplify to
template<typename T>
class vec{
public:
// ...
};
template<typename T>
vec<T> operator + (vec<T> a, const vec<T>& b){
a += b;
return a;
}
Here's a few more notes:
operator+()
(which you nicely implemented on top of operator+=()
, BTW) should take its left argument per copy. inline
, define them so. operator+=()
return a non-const
reference, because everybody expects f(m1+=m2)
to work even if f()
takes its argument as a non-const
reference. vec& operator += (const vec&);
. (You cannot do this outside of the template, though - for example, when defining that operator outside of the class.) std::vector
's index type is spelled std::vector<blah>::size_type
, not unsigned short
. Upvotes: 6
Reputation: 5732
The return type here:
inline friend vec<T> operator + (const vec<T>&, const vec<T>&);
Does not match here:
template<typename T>
vec<T>& operator + (const vec<T>& a, const vec<T>& b){
vec<T> product = a;
product += b;
return product;
} // Addition.
Upvotes: 6