/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

namespace Magnum {
/** @page compilation-speedup Speeding up compilation
@brief Techniques for reducing compilation times.

@section compilation-forward-declarations Forward declarations instead of includes

Essential thing when speeding up compilation is reducing number of `#``include`
directives in both headers and source files. %Magnum is strictly applying this
policy in all header files, so all types which are not directly used in the
header have only forward declarations.

For example, when including @ref Magnum.h, you get shortcut typedefs for
floating-point vectors and matrices like @ref Vector3 and @ref Matrix4, but to
actually use any of them, you have to include the respective header, e.g.
@ref Math/Vector3.h.

You are encouraged to use forward declarations also in your code. However, for
some types it can be too cumbersome -- e.g. too many template parameters,
typedefs etc. In this case a header with forward declarations is usually
available, each namespace has its own:

 - @ref Math/Math.h
 - @ref Magnum.h
 - @ref DebugTools/DebugTools.h
 - @ref SceneGraph/SceneGraph.h
 - @ref Shaders/Shaders.h
 - @ref Shapes/Shapes.h
 - @ref Text/Text.h
 - @ref Trade/Trade.h

@section compilation-speedup-templates Templates

Many things in %Magnum are templated to allow handling of various types and
sizes of data, for example whole scene graph can operate either with @ref Float
or @ref Double data type. However, having templated classes and function
usually means that the compiler compiles the whole templated code again in each
compilation unit (i.e. source file). In linking stage of the application or
library the duplicates are just thrown out, which is a waste of compilation
time. A few techniques are employed in %Magnum to avoid this.

@subsection compilation-speedup-hpp Template headers and implementation files

When templated code is too large, it is not stored in header file, but in
so-called *template implementation file*. Generally, all header files in
%Magnum have `*.h` extension and all source files have `*.cpp` extension.
Template implementation files have `*.hpp` extension, hinting that they are
something between `*.h` and `*.cpp` files.

Template implementation file can be included along the header itself and it
will just work, but it will negatively affect compilation time. If you are
using one template specialization in many places, the compiler performs
compilation of the same template specialization many times, as said above.
Template implementation files give you the ability to explicitly instantiate
the template only once in some dedicated source file. Then you can include just
the header everywhere else and leave the rest on the linker.

Templated classes having code in template implementation files state in their
documentation all common specializations that are already compiled in the
libraries. So, unless the templated class is too generic or you need something
special, you don't have to mess with template implementation files at all. See
@ref SceneGraph::Object or @ref SceneGraph::AbstractCamera for an example.

Sometimes, however, you need to use your own specialization and that's why
template implementation files are installed along with the library. For example
we want to use @ref SceneGraph::Object "Object" from @ref SceneGraph with
@ref SceneGraph::BasicMatrixTransformation3D "BasicMatrixTransformation3D" with
@ref Double instead of @ref Float as underlying type, because our scene will
span the whole universe. We include the implementation file in dedicated source
file and explicitly instantiate the template:
@code
// Object.cpp
#include "SceneGraph/Object.hpp"
#include "SceneGraph/MatrixTransformation3D.h"

using namespace Magnum;

template class SceneGraph::Object<SceneGraph::BasicMatrixTransformation3D<Double>>;
@endcode

All other files using the same object specialization now need to include only
@ref SceneGraph/Object.h header. Thus the @ref SceneGraph::Object "Object"
specialization will be compiled only once in our `Object.cpp` file, saving
precious compilation time.

@subsection compilation-speedup-extern-templates Extern templates

Keyword `extern template` is a new thing in C++11, attempting to solve
compilation time problems related to templated code. However, on some compilers
it causes conflicting symbol errors when used on whole classes, thus in %Magnum
it's used only for specific functions.

This is completely transparent to end user, so no special care is needed.
Extern template is used for example for @ref debugoperators "debug operators"
for common types of matrices and vectors.

*/
}
