0

The story

My main.cpp is getting really cluttered so I decided to separate other functions from it (some helper functions for IO operations in main()).

The problem

The files compile fine when the functions are within main.cpp. When I put them to a .h - .cpp pair, I get the following compiler error.

The line I use:

g++ -I ./headers/ ./definitions/*.cpp -o main.o main.cpp

The error:

    Undefined symbols for architecture x86_64:
      "void showSettings<double>(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>,
std::__1::allocator<char> >,
std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>,
std::__1::allocator<char> > > > const&,
std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, 
std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, 
std::__1::allocator<char> > > > const&, int, int, double, double, int, int, int, int, int)", 
referenced from:
          _main in main-7k1oIa.o
    ld: symbol(s) not found for architecture x86_64

The only working solution right now is to bring the functions back to main.cpp. I've included all necessary headers, using namespace std and prepending std:: to vector and string but the error keeps showing.

If it's of any help, the code that appears in the error is:

template <typename inputType>
void showSettings(  const vector<string> &a,
                    const vector<string> &b,
                    int eq,
                    int meth,
                    inputType root1,
                    inputType root2,
                    int sigs,
                    int showPerLoop,
                    int plotRoots,
                    int loopMode,
                    int minLoops)
Nogurenn
  • 858
  • 3
  • 11
  • 28
  • possible duplicate of [Why can templates only be implemented in the header file?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – Mike Seymour Jan 06 '14 at 12:26

1 Answers1

1

Templates are only instantiated when called, so if no function in your secondary .cpp file calls showSettings with a <double>, then the function wasn't created.

Generally, you want to leave template functions in a .h file so that the actual definition is visible when needed.

(See also: Why should the implementation and the declaration of a template class be in the same header file?)

Community
  • 1
  • 1
tabstop
  • 1,751
  • 11
  • 10
  • Let me clarify: You mean I have to give the implementation of the template to `.h` file and remove it from the `.cpp` file? – Nogurenn Jan 06 '14 at 12:28
  • I've moved the entire template definition to the `.h` file and added a `using namespace std`. It compiled. Will this suffice, or is it better to just supply `std::` to the requiring things like `vector` and `string`? – Nogurenn Jan 06 '14 at 12:37
  • @solitude yes. The `.cpp` file should be empty in this case. – Paweł Stawarz Jan 06 '14 at 12:39
  • @PawełStawarz The link provided by this answer mentions that explicit instantiation of the template in the `.cpp` file saves me from having to include definitions in the `.h` file. Will it be better that way or putting the entire definition in the header file is just as fine? – Nogurenn Jan 06 '14 at 12:46
  • @solitude explicitly instantiating the template inside a `*.cpp` means you didn't really need a template in the first place. If you want the template to be valid for classes that are yet to be declared in the future, you need to provide the definitions inside the header. – Paweł Stawarz Jan 06 '14 at 12:59
  • @solitude you shouldn't put 'using namespace std' in a header, as it'll pollute the namespace of anyone who uses the header. Use 'std::' where necessary instead. – Tom Tanner Jan 06 '14 at 14:42