Automatically separate class definitions from declarations?

后端 未结 4 1818
遥遥无期
遥遥无期 2020-12-19 21:35

I am using a library that consists almost entirely of templated classes and functions in header files, like this:

// foo.h
template

        
相关标签:
4条回答
  • 2020-12-19 22:14

    Try using precompiled headers. I know GCC and MSVC support this feature. Usage is vender-specific, though.

    0 讨论(0)
  • 2020-12-19 22:16

    C++0x will fix your compile time issues with extern templates. I don't know an automatic way to do what you ask, though.

    0 讨论(0)
  • 2020-12-19 22:26

    I have been working on the very same issue for quite a while now. In the solution you're proposing, you are defining your template classes twice. It will be ok if it defines the same stuff (in the same order), but you're bound to have problems sooner or later.

    What i have come up with is to consider the problem the other way around. As long as you are not specializing your implementation, it works gracefully.

    It uses two macros, which avois having to update template arguments in implementation file (be careful, though, if you want to add default template arguments to the class).

    // foo.h
    #define FOO_TEMPLATE template<typename T>
    #define FOO_CLASS Foo<T>
    
    FOO_TEMPLATE
    class Foo {
      Foo();
      void computeXYZ();
    };
    
    // foo_impl.h
    #include "foo.h"
    FOO_TEMPLATE
    FOO_CLASS::Foo(){}
    
    FOO_TEMPLATE
    void FOO_CLASS::computeXYZ() { /* heavy code */ }
    

    By doing this, you essentially work the same way you do with non-template classes (you can do the same thing with template functions, of course).

    EDIT : about the extern keyword in c++0x

    I believe the extern keyword in c++0x will help, but it won't solve everything magically !

    From this article,

    Extern Templates

    Every module that instantiates a template essentially creates a copy of it in the object code. Then, it's up to the linker to dispose of all of the redundant object code at the very last stage, thus slowing the critical edit-compile-link cycle that makes up a programmer's day (or sometimes daydreams). To short-circuit this object code garbage collection, a number of compiler vendors have already implemented an extern keyword that can go in front of templates. This is a case of standardization codifying existing industry practice (pun intended). In practice, this is implemented by sending a notice to the compiler basically to "not instantiate this here":

    extern template class std::vector;
    
    0 讨论(0)
  • 2020-12-19 22:32

    We use lzz which splits out a single file into a separate header and translation unit. By default, it would normally put the template definitions into the header too, however, you can specify that you don't want this to happen.

    To show you how you might use it consider the following:

    // t.cc
    #include "b.h"
    #include "c.h"
    
    template <typename T> 
    class A {
      void foo () {
        C c;
        c.foo ();
        b.foo ();
      }
      B b;
    }
    

    Take the above file and copy it to 't.lzz' file. Place any #include directives into separate $hdr and $src blocks as necessary:

    // t.lzz
    $hdr
    #include "b.h"
    $end
    
    $src
    #include "c.h"
    $end
    
    template <typename T> 
    class A {
      void foo () {
        C c;
        c.foo ();
        b.foo ();
      }
      B b;
    }
    

    Now finally, run lzz over the file specifying that it places the template definitions into the source file. You can either do this using a $pragma in the source file, or you can use the command line option "-ts":

    This will result in the following files being generated:

    // t.h
    //
    
    #ifndef LZZ_t_h
    #define LZZ_t_h
    #include "b.h"
    #undef LZZ_INLINE
    #ifdef LZZ_ENABLE_INLINE
    #define LZZ_INLINE inline
    #else
    #define LZZ_INLINE       
    #endif
    template <typename T>
    class A
    {
      void foo ();
      B b;
    };
    #undef LZZ_INLINE
    #endif
    

    And:

    // t.cpp
    //
    
    #include "t.h"
    #include "c.h"
    #define LZZ_INLINE inline
    template <typename T>
    void A <T>::foo ()
              {
        C c;
        c.foo ();
        b.foo ();
      }
    #undef LZZ_INLINE
    

    You can then run these through some grep/sed commands to remove the LZZ helper macros.

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