C++ template function compiles in header but not implementation

前端 未结 6 1670
梦谈多话
梦谈多话 2020-12-02 14:53

I\'m trying to learn templates and I\'ve run into this confounding error. I\'m declaring some functions in a header file and I want to make a separate implementation file w

6条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-02 15:30

    The problem you're having is that the compiler doesn't know which versions of your template to instantiate. When you move the implementation of your function to x.cpp it is in a different translation unit from main.cpp, and main.cpp can't link to a particular instantiation because it doesn't exist in that context. This is a well-known issue with C++ templates. There are a few solutions:

    1) Just put the definitions directly in the .h file, as you were doing before. This has pros & cons, including solving the problem (pro), possibly making the code less readable & on some compilers harder to debug (con) and maybe increasing code bloat (con).

    2) Put the implementation in x.cpp, and #include "x.cpp" from within x.h. If this seems funky and wrong, just keep in mind that #include does nothing more than read the specified file and compile it as if that file were part of x.cpp In other words, this does exactly what solution #1 does above, but it keeps them in seperate physical files. When doing this kind of thing, it is critical that you not try to compile the #included file on it's own. For this reason, I usually give these kinds of files an hpp extension to distinguish them from h files and from cpp files.

    File: dumper2.h

    #include 
    #include 
    #include 
    
    void test();
    template  void dumpVector( std::vector v,std::string sep);
    #include "dumper2.hpp"
    

    File: dumper2.hpp

    template  void dumpVector(std::vector v, std::string sep) {
      typename std::vector::iterator vi;
    
      vi = v.begin();
      std::cout << *vi;
      vi++;
      for (;vi

    3) Since the problem is that a particular instantiation of dumpVector is not known to the translation unit that is trying to use it, you can force a specific instantiation of it in the same translation unit as where the template is defined. Simply by adding this: template void dumpVector(std::vector v, std::string sep); ... to the file where the template is defined. Doing this, you no longer have to #include the hpp file from within the h file:

    File: dumper2.h

    #include 
    #include 
    #include 
    
    void test();
    template  void dumpVector( std::vector v,std::string sep);
    

    File: dumper2.cpp

    template  void dumpVector(std::vector v, std::string sep) {
      typename std::vector::iterator vi;
    
      vi = v.begin();
      std::cout << *vi;
      vi++;
      for (;vi(std::vector v, std::string sep);
    

    By the way, and as a total aside, your template function is taking a vector by-value. You may not want to do this, and pass it by reference or pointer or, better yet, pass iterators instead to avoid making a temporary & copying the whole vector.

提交回复
热议问题