Splitting templated C++ classes into .hpp/.cpp files--is it possible?

前端 未结 16 855
被撕碎了的回忆
被撕碎了的回忆 2020-11-22 17:27

I am getting errors trying to compile a C++ template class which is split between a .hpp and .cpp file:

$ g++ -c -o main.o main.cpp         


        
相关标签:
16条回答
  • 2020-11-22 17:45

    The problem is that a template doesn't generate an actual class, it's just a template telling the compiler how to generate a class. You need to generate a concrete class.

    The easy and natural way is to put the methods in the header file. But there is another way.

    In your .cpp file, if you have a reference to every template instantiation and method you require, the compiler will generate them there for use throughout your project.

    new stack.cpp:

    #include <iostream>
    #include "stack.hpp"
    template <typename Type> stack<Type>::stack() {
            std::cerr << "Hello, stack " << this << "!" << std::endl;
    }
    template <typename Type> stack<Type>::~stack() {
            std::cerr << "Goodbye, stack " << this << "." << std::endl;
    }
    static void DummyFunc() {
        static stack<int> stack_int;  // generates the constructor and destructor code
        // ... any other method invocations need to go here to produce the method code
    }
    
    0 讨论(0)
  • 2020-11-22 17:48

    I believe there are two main reasons for trying to seperate templated code into a header and a cpp:

    One is for mere elegance. We all like to write code that is wasy to read, manage and is reusable later.

    Other is reduction of compilation times.

    I am currently (as always) coding simulation software in conjuction with OpenCL and we like to keep code so it can be run using float (cl_float) or double (cl_double) types as needed depending on HW capability. Right now this is done using a #define REAL at the beginning of the code, but this is not very elegant. Changing desired precision requires recompiling the application. Since there are no real run-time types, we have to live with this for the time being. Luckily OpenCL kernels are compiled runtime, and a simple sizeof(REAL) allows us to alter the kernel code runtime accordingly.

    The much bigger problem is that even though the application is modular, when developing auxiliary classes (such as those that pre-calculate simulation constants) also have to be templated. These classes all appear at least once on the top of the class dependency tree, as the final template class Simulation will have an instance of one of these factory classes, meaning that practically every time I make a minor change to the factory class, the entire software has to be rebuilt. This is very annoying, but I cannot seem to find a better solution.

    0 讨论(0)
  • 2020-11-22 17:48

    Sometimes it is possible to have most of implementation hidden in cpp file, if you can extract common functionality foo all template parameters into non-template class (possibly type-unsafe). Then header will contain redirection calls to that class. Similar approach is used, when fighting with "template bloat" problem.

    0 讨论(0)
  • 2020-11-22 17:49

    1) Remember the main reason to separate .h and .cpp files is to hide the class implementation as a separately-compiled Obj code that can be linked to the user’s code that included a .h of the class.

    2) Non-template classes have all variables concretely and specifically defined in .h and .cpp files. So the compiler will have the need information about all data types used in the class before compiling/translating  generating the object/machine code Template classes have no information about the specific data type before the user of the class instantiate an object passing the required data type:

            TClass<int> myObj;
    

    3) Only after this instantiation, the complier generate the specific version of the template class to match the passed data type(s).

    4) Therefore, .cpp Can NOT be compiled separately without knowing the users specific data type. So it has to stay as source code within “.h” until the user specify the required data type then, it can be generated to a specific data type then compiled

    0 讨论(0)
  • 2020-11-22 17:50

    Because templates are compiled when required, this forces a restriction for multi-file projects: the implementation (definition) of a template class or function must be in the same file as its declaration. That means that we cannot separate the interface in a separate header file, and that we must include both interface and implementation in any file that uses the templates.

    0 讨论(0)
  • 2020-11-22 17:51

    No, it's not possible. Not without the export keyword, which for all intents and purposes doesn't really exist.

    The best you can do is put your function implementations in a ".tcc" or ".tpp" file, and #include the .tcc file at the end of your .hpp file. However this is merely cosmetic; it's still the same as implementing everything in header files. This is simply the price you pay for using templates.

    0 讨论(0)
提交回复
热议问题