Question

I have several template classes Impl (with some abstract methods) that are partially implemented in CPP files so that I need to explicitly instantiate my templates for the linker to find it, like this:

template class Impl<T0>;
template class Impl<T1>;
template class Impl<T2>;
...
template class Impl<Tx>;

As the number of types Tx grows, I would like to find a better way than to manually expand these lists of explicit instantiations in all necessary files. I thought I could use variadic templates for this, so I tried the following:

template <template <class> class, class...>
struct type_map;

template <template <class> class BaseT, class... Ts>
struct type_map<BaseT, std::tuple<Ts...>> {
    using type = std::tuple<BaseT<Ts>...>;
};

typedef std::tuple<T0, T1, T2> MyTypes;

And in the CPP file:

template class type_map<Impl, MyTypes>;

However, this didn't instantiate the templates as I intended (the linker complained about the missing symbols).

Is there a way to make this approach work (i.e. instantiate the template without instantiating an object of it) or a totally different approach that could solve my problem in this situation?

Was it helpful?

Solution

I don't think you can do this with variadic templates, but you can do it with the preprocessor.

I see two options. One would be to use Boost.Preprocessor:

// Definitions:
#define ARGUMENTS (T0)(T1)(T2)(T3)(Tx)

#define INSTANTIATE(maUnused, maTemplate, maType) \
  template class maTemplate<maType>;


// Usage:
BOOST_PP_SEQ_FOR_EACH(INSTANTIATE, Impl, ARGUMENTS)

BOOST_PP_SEQ_FOR_EACH(INSTANTIATE, Impl2, ARGUMENTS)

Another option would be to use the X macro trick:

x.hpp

X(T0)
X(T1)
X(T2)
X(T3)
X(Tx)

#undef X

using_file.cpp

#define X(maType) template class Impl<maType>;
#include "x.hpp"

#define X(maType) template class Impl2<maType>;
#include "x.hpp"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top