Explicit implementation of the inlaid pattern

So a colleague and I discussed the benefits of explicit template creation when it came to reducing compile time, separating declaration from definition, and not affecting the performance of the C ++ math library I wrote that is being used for other projects.

Essentially I have a library of useful math functions designed to work with primitives like Vector3, Vector4, Quaternion, etc. They are all designed to be used with a template argument that is float or double (and in some cases int).

So I don't need to write these functions twice, once for float, once for double, the implementation of the functions is templated, for example:

template<typename T>
Vector3<T> foo(const Vector4<T>& a, 
               const Quaternion<T>& b) 
{ do something... }

      

All are defined in .h files (so they are implicitly marked for inlining). Most of these functions are short and will hopefully be inlined at compile time.

The headers are getting pretty big, although compile time is growing and it's hard to find the existence of functions just by looking at the headers (one of the many reasons I like to separate the declaration from the implementations).

So I can use explicit template instantiation in the accompanying .cpp file like:

  //in .h
  template<typename T>
  Vector3<T> foo(const Vector4<T>& a, 
                 const Quaternion<T>& b) 
  { do something... }

  //in .cpp
  template Vector3<float> foo<float>(const Vector4<float>& a, 
                                     const Quaternion<float>& b);
  template Vector3<double> foo<double>(const Vector4<double>& a, 
                                       const Quaternion<double>& b);

      

Should this help with compile time? Will this affect the ability to enable features? Are the answers to any of these questions primarily a compiler?

An added benefit is that it checks that the function compiles even if I haven't used it yet.

Also I could do this:

  //in .h
  template<typename T>
  Vector3<T> foo(const Vector4<T>& a, 
                 const Quaternion<T>& b);

  //in .cpp
  template<typename T>
  Vector3<T> foo(const Vector4<T>& a, 
                 const Quaternion<T>& b) 
  { do something... }

  template Vector3<float> foo<float>(const Vector4<float>& a, 
                                     const Quaternion<float>& b);
  template Vector3<double> foo<double>(const Vector4<double>& a, 
                                       const Quaternion<double>& b);

      

Same questions for this method:

Should this help with compile time? Will this affect the ability to enable features? Are the answers to any of these questions primarily a compiler?

I expect embeddability will definitely be affected given that the definition is not in the header.

The good news is that it manages to decouple the declaration and definition of template functions (for specific template arguments) without having to do something like using the .inl included at the bottom of the .h file. It also hides the implementation from the user of the library, which is useful (but not really necessary yet), but templates can still be used, so I don't need to execute the function N times.

Is there a way to allow embedding by customizing the method?

I found it difficult to just find an answer to these questions, and the standards specifications are hard to understand on these topics (at least for me).

BTW, it is expected to compile with VS2010, VS2012 and GCC 4.7.

Any help would be greatly appreciated.

thank

+3


source to share


1 answer


I assume your technique is designed to do the same as the answer to this question: Effect of template creation on compile time

In order to achieve the desired result, you also need to prevent automatic instantiation by declaring explicit instances in the header with extern

. See Explicitly declaring instantiation with extern

//in .h
template<typename T>
Vector3<T> foo(const Vector4<T>& a, 
               const Quaternion<T>& b);

extern template Vector3<float> foo<float>(const Vector4<float>& a, 
                                          const Quaternion<float>& b);

extern template Vector3<double> foo<double>(const Vector4<double>& a, 
                                            const Quaternion<double>& b);

//in .cpp
template<typename T>
Vector3<T> foo(const Vector4<T>& a, 
               const Quaternion<T>& b) 
{ /* do something...*/ }

template Vector3<float> foo<float>(const Vector4<float>& a, 
                                   const Quaternion<float>& b);
template Vector3<double> foo<double>(const Vector4<double>& a, 
                                     const Quaternion<double>& b);

      

Should this help with compile time? Will this affect the ability to enable features? Are the answers to any of these questions primarily a compiler?



The answer is very compiler-dependent - and needs to be more precise empirically, but we can generalize it.

We can assume that the increase in compile time does not come from the cost of parsing the syntax of the extra corner of the template template, but from the cost of the (complex) process of instantiating the template. If so, the cost of using a given template specialization across multiple translation units should dramatically increase compilation time only if instantiation is expensive and the compiler executes the instance more than once.

The C ++ standard implicitly allows the compiler to execute an instance of each unique specialization only once for all translation units. That is, an instance of template functions can be deferred and executed after initial compilation, as described in the Comeau documentation . Whether or not this optimization is implemented is compiler-dependent, but of course it was not implemented in any version of MSVC until 2015.

If your compiler is executing an instance at reference time, this method will prevent inlining if the compiler does not support cross-module insertion. Later versions of MSVC, GCC and Clang support cross-module supporting connection times with an optional linker (LTCG or LTO). See Can the built-in linker function?

+2


source







All Articles