Template class - no characters found

I saw several related posts , but I can’t understand what I need to do to fix the program that I create for my entry-level C ++ class.

My mistakes:

Build Final Project of project Final Project with configuration Debug Ld "build/Debug/Final Project" normal x86_64 cd "/Users/nick/Dropbox/|Syncs/Xcode/Final Project" setenv MACOSX_DEPLOYMENT_TARGET 10.6 /Developer/usr/bin/g++-4.2 -arch x86_64 -isysroot /Developer/SDKs/MacOSX10.6.sdk "- L/Users/nick/Dropbox/|Syncs/Xcode/Final Project/build/Debug" "-F/Users/nick/Dropbox/|Syncs/Xcode/Final Project/build/Debug" -filelist "/Users/nick/Dropbox/|Syncs/Xcode/Final Project/build/Final Project.build/Debug/Final Project.build/Objects-normal/x86_64/Final Project.LinkFileList" -mmacosx-version-min=10.6 -o "/Users/nick/Dropbox/|Syncs/Xcode/Final Project/build/Debug/Final Project" Undefined symbols: "Vector<double>::Vector()", referenced from: _main in main.o "Vector<double>::length()", referenced from: _main in main.o "Vector<double>::Vector(double const&, double const&, double const&)", referenced from: _main in main.o _main in main.o "Vector<double>::getx() const", referenced from: _main in main.o _main in main.o "Vector<double>::gety() const", referenced from: _main in main.o _main in main.o ld: symbol(s) not found collect2: ld returned 1 exit status 

Here is what I have:

 //main.cpp #include <iostream> #include "Vector.h" int main () { Vector<double> a(1, 2, 3); Vector<double> b(2, 4, 4); Vector<double> c; std::cout << "Length: " << b.length() << std::endl; std::cout << b.getx() << " ," << b.gety() << std::endl; std::cout << c.getx() << " , " << c.gety() << std::endl; return 0; } 

and

 //Vector.h template <class T> class Vector { T x, y, z; public: //constructors Vector(); Vector(const T& x, const T& y, const T& z); Vector(const Vector& u); //accessors T getx() const; T gety() const; T getz() const; //mutators void setx(const T& x); void sety(const T& y); void setz(const T& z); //operations void operator-(); Vector plus(const Vector& v); Vector minus(const Vector& v); Vector cross(const Vector& v); T dot(const Vector& v); void times(const T& s); T length(); }; 

and Vector.cpp (although I cut off some code that duplicates somewhat - accessors and mutators for y and z, for example)

 //Vector.cpp #include "Vector.h" #include <iostream> #include <math.h> template class Vector<int>; template class Vector<double>; //default constructor template <class T> Vector<T>::Vector(): x(0), y(0), z(0) {} //constructor template <class T> Vector<T>::Vector(const T& x, const T& y, const T& z) { setx(x); sety(y); setz(z); } //copy constructor template <class T> Vector<T>::Vector(const Vector& u) { x = u.getx(); y = u.gety(); z = u.getz(); } //x accessor template <class T> T Vector<T>::getx() const { return x; } //y accessor //z accessor //x mutator template <class T> void Vector<T>::setx(const T& x) { Vector::x = x; } //y mutator //z mutator //negated Vector template <class T> void Vector<T>::operator-() { setx(-this->getx()); sety(-this->gety()); setz(-this->getz()); } //sum template <class T> Vector<T> Vector<T>::plus(const Vector& v) { Vector ret((getx() + v.getx()), (gety() + v.gety()), (getz() + v.getz())); return ret; } //difference template <class T> Vector<T> Vector<T>::minus(const Vector& v) { Vector ret((getx() - v.getx()), (gety() - v.gety()), (getz() - v.getz())); return ret; } //cross product template <class T> Vector<T> Vector<T>::cross(const Vector& v) { Vector ret; ret.setx(gety()*v.getz() - getz()*v.gety()); ret.sety(getz()*v.getx() - getx()*v.getz()); ret.setz(getx()*v.gety() - gety()*v.getx()); return ret; } //dot product template <class T> T Vector<T>::dot(const Vector& v) { return (getx()*v.getx() + gety()*v.gety() + getz()*v.getz()); } //scalar times Vector template <class T> void Vector<T>::times(const T& s) { setx(getx()*s); sety(gety()*s); setz(getz()*s); } //length of Vector template <class T> T Vector<T>::length() { return sqrt((this->dot(*this))); } 

So what the hell is going on? Is it because I have a separate header and .cpp file for Vector? How to get the main function for recognizing functions of the Vector class?

+6
c ++ symbols templates
source share
4 answers

A detailed explanation is available at http://www.parashift.com/c++-faq-lite/templates.html

[35.12] Why can't I separate the definition of my template from its declaration and put it in a .cpp file?

If you want to know how to fix this situation, read the following two frequently asked questions. But to understand why this is so, first accept the following facts:

  • A template is not a class or function. A template is a “template” that the compiler uses to generate a family of classes or functions.
  • In order for the compiler to generate code, it must see both the definition of the template (and not just the declaration), as well as the specific types / everything that is used to "populate" the template. For example, if you are trying to use Foo, the compiler should see both the Foo pattern and the fact that you are trying to create a specific Foo.
  • Your compiler probably does not remember the details of one .cpp file when it compiles another .cpp file. It is possible, but most of them do not, and if you read this FAQ, it almost certainly does not. BTW is called a "separate compilation model."

Now, based on these facts, here is an example that shows why everything is as it is. Suppose you have a Foo template like this:

 template<typename T> class Foo { public: Foo(); void someMethod(T x); private: T x; }; 

Along with similar definitions for member functions:

  template<typename T> Foo<T>::Foo() { ... } template<typename T> void Foo<T>::someMethod(T x) { ... } 

Now suppose you have the code in the Bar.cpp file that Foo uses:

//Bar.cpp

 void blah_blah_blah() { ... Foo<int> f; f.someMethod(5); ... } 

Clearly, somewhere, someone will have to use the “template” to define the constructor and to define someMethod () and create instances when T is actually int. But if you entered the definition of the constructor and someMethod () in the Foo.cpp file, the compiler will see the template code when compiling Foo.cpp, and he will see Foo when he compiles Bar.cpp, but never when he saw the template code, and foo. Thus, by rule number 2 above, he will never be able to generate code for Foo :: someMethod ().

Note to experts: I obviously made a few simplifications above. This was intentional, so please do not complain too loudly. If you know the difference between a .cpp file and a compilation unit, the difference between a class template and a template class, and the fact that templates are really not just famous macros, then do not complain: this specific question / answer was not directed to you. I simplified everything so that newcomers “understand”, even if it offends some experts.

[35.13] How to avoid linker errors with my template functions?

Tell your C ++ compiler which instances should run when it compiles your .cpp file.

As an example, consider the header file foo.h, which contains the following template function declaration:

// File "foo.h"

  template<typename T> extern void foo(); 

Now suppose the foo.cpp file actually defines this template function:

// File "foo.cpp"

  #include <iostream> #include "foo.h" template<typename T> void foo() { std::cout << "Here I am!\n"; } 

Suppose the main.cpp file uses this template function by calling foo ():

// File "main.cpp"

  #include "foo.h" int main() { foo<int>(); ... } 

If you compile and (try) linking these two .cpp files, most compilers will generate linker errors. There are three solutions for this. The first solution is to physically move the definition of the template function to the .h file, even if it is not a built-in function. This solution may (or may not be!) Cause significant bloating of code, which means that the size of the executable file can increase dramatically (or, if your compiler is smart enough, cannot, try it and see).

Another solution is to leave the template function definition in the .cpp file and just add the void foo () line template; to this file:

// File "foo.cpp"

  #include <iostream> #include "foo.h" template<typename T> void foo() { std::cout << "Here I am!\n"; } template void foo<int>(); 

If you cannot modify foo.cpp, simply create a new .cpp file, for example foo-impl.cpp, as follows:

// File "foo-impl.cpp"

  #include "foo.cpp" template void foo<int>(); 

Note that foo-impl.cpp # includes the .cpp file, not the .h file.

+10
source share

The simplest solution here is to include your .cc / .cpp files and include these files in the header files. For example, if we have source.cpp and header.h , and we want to use the source file inside the main.cc file, add #include "header.h" in source.cpp and #include "source.cpp" to your main.cpp .

Not sure if the compiler is optimizing this, but it worked for me.

+2
source share

Is it because I have a separate header and .cpp file for Vector?

Yes.

How do I get my main function to recognize the functions of my Vector class?

Place the definitions of the function templates and the functions of the member of the class template in the header file.

In fact, the template definition must be available in main.cpp to create the template using arguments ( double in this case).

+1
source share

the problem is not really solved by including cpp instead of the header. Its template and templates do not have cpp. create a title and save the rest in * .inl instead of * .cpp. include inl at the end of your * .h. it will do it. Don't # include anything in inl.

-4
source share

All Articles