FAQ 13.10 Is there an easy way to swap between inline and non- inline code?

FAQ 13.10 Is there an easy way to swap between inline and non-inline code?

graphics/new_icon.gif

Yes, with a little macro magic.

Most projects should turn off inlining during development. That is, they use a compiler option that causes the compiler to not inline any inline functions. This can make the code easier to debug, but it still doesn't help the edit-compile-debug problem mentioned in FAQ 13.08. For example, turning off inline expansion via a compiler option does not improve compile-time performance the compiler still has to parse the body of every inline function in a header every time a source file is compiled that includes the header. Furthermore, depending on the compiler, turning off inline expansion may increase code bulk the compiler may create duplicate static copies of each inline function seen by the compiler during every compilation unit. Finally, and probably most important, turning off inline expansion doesn't help the "recompile the world" problem (see FAQ 13.08) since the inline functions are still in the include files.

Although macros are evil, this is one of the areas where they can be used to bypass the compile-time overhead mentioned in FAQ 13.08. The strategy is straightforward. First, define all inline functions outside the class body in a separate file (call this the .inl file or .ipp file). Then, in the .inl file, change the keyword inline to the preprocessor symbol INLINE. Finally, conditionally #include the .inl file from either the bottom of the .hpp file or from the .cpp file, depending on whether or not INLINE should become inline or nothing.

In the following example, inline.hpp defines a macro INLINE to be either the keyword inline or nothing, depending on whether the USE_INLINE symbol is #defined. For example, if the compiler supports the -D option as a way to #define a symbol, compiling with -DUSE_INLINE causes INLINE to become inline. Here is file inline.hpp.

 #ifndef INLINE_HPP #define INLINE_HPP #ifdef USE_INLINE   #define INLINE  inline #else   #define INLINE  /*nothing*/ #endif #endif 

File Fred.hpp defines class Fred with two member functions, f() and g(). If the symbol USE_INLINE is #defined, file Fred.inl is #included from Fred.hpp. Here is file Fred.hpp.

 #ifndef FRED_HPP #define FRED_HPP #include "inline.hpp" class Fred { public:   void f() throw();                                  <-- 1   void g() throw(); }; #ifdef USE_INLINE                                    <-- 2   #include "Fred.inl" #endif #endif 

(1) No code in the class body

(2) #ifdef means "if defined"

File Fred.inl defines Fred::f() preceded with the symbol INLINE. Note that Fred.inl does not #include "Fred.hpp". Here is file Fred.inl.

 #include <iostream> using namespace std; INLINE void Fred::f() throw()                        <-- 1 { cout << "Fred::f() is optionally inlined\n"; } 

(1) Uses INLINE, not inline

File Fred.cpp defines Fred::g() as non-inline. If the symbol USE_INLINE is not #defined, file Fred.inl is #included from Fred.cpp. Here is file Fred.cpp.

 #include "Fred.hpp" using namespace std; #ifndef USE_INLINE                                   <-- 1   #include "Fred.inl" #endif void Fred::g() throw() { cout << "Fred::g() is never inlined\n"; } 

(1) #ifndef means "if not defined"

It is important to note that users of Fred don't have to be aware of the .inl file. For example, if file UserCode.cpp uses a Fred object, it won't need to change due to the INLINE magic. Here is a sample file that uses a Fred object, file UserCode.cpp.

 #include "Fred.hpp" int main() {   Fred x;   x.f();   x.g(); } 

This strategy can be easily modified to allow class-specific inlining. Simply replace the line #include "inline.hpp" with the contents of that file, then change USE_INLINE to USE_INLINE_Fred and INLINE to INLINE_Fred throughout.



C++ FAQs
C Programming FAQs: Frequently Asked Questions
ISBN: 0201845199
EAN: 2147483647
Year: 2005
Pages: 566
Authors: Steve Summit

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net