Search code examples
c++boostmetaprogrammingforward-declarationboost-hana

What is the use case of boost::hana forward declaration headers?


Most of the hana headers include also forward declaration headers contained in the subfolder fwd, e.g. #include<boost/hana/fwd/pair.hpp.

AFAIK forward declaration headers declare things instead of defining them, so the user can have a access limited to pointers (and references) to the functions and objects.

What sense does it make for boost::hana, which is header-only templated library? The only thing that comes to my mind is that forward declarations are good enough if you do not intend to instantiate the declared templates, but then - what is the point of using them in the first place?

By looking at the library source I sense it is something very smart, which I still do not comprehend.


Imagine I need only very specific instances of the boost::hana templates. Would it work, if I define and instantiate them in one translation unit, and link to them from all the other units, using forward declarations?


Solution

  • There is a little information on this in the manual here:

    This subdirectory contains the forward declaration of everything in the library. It is essentially a mirror of the boost/hana/ directory, except all the headers contain only forward declarations and documentation. For example, to include the hana::tuple container, one can use the boost/hana/tuple.hpp header. However, if one only wants the forward declaration of that container, the boost/hana/fwd/tuple.hpp header can be used instead. Note that forward declarations for headers in boost/hana/ext/ and boost/hana/functional/ are not provided.

    Also from a discussion with the author here:

    The rationale is so that we can #include lightweight declarations instead of full blown definitions when only a declaration is requried. This can help with compile times. Also, it’s necessary for some circularly-dependent stuff.

    and:

    And finally, I think it makes for a nice separation between interface and implementation, and also it gives a place to systematically put documentation. Since the implementation is sometimes hairy, I think it’s nice not to entangle the documentation with it.

    There it is straight from the horse's mouth. I've found it is quite necessary to separate implementation for the whole chicken/egg problem with circular dependencies. This is a clean way of doing that, that I've adopted in my own projects.