实例化多个模板

Instantiating multiple templates

本文关键字:实例化      更新时间:2023-10-16

如果我有一个名为Tuple<T, SIZE>的类,并且我想要在编译库时实例化20个不同的浮动模板(这样用户就不会遇到链接错误):

template Tuple<float, 1>;
template Tuple<float, 2>;
...
template Tuple<float, 20>;

有什么方法可以递归地执行上面的操作吗?也许允许它是灵活的,这样我就可以把它放在我想要的任何数字上,它为我实例化类?

编辑:到目前为止我尝试了什么(似乎不起作用):

template <typename T, unsigned int MAX_RANGE>
class AllTuples
{
  Tuple<T, MAX_RANGE> y;
  AllTuples<T, MAX_RANGE - 1> x;
};
template <typename T>
class AllTuples<T, 1>
{
  Tuple<T, 1> x;
};
AllTuples<float, 10>;

很抱歉你运气不好。除非使用预处理器元编程库(boost.pp),否则无法实现自动化。不使用模板元编程。

您生成的是Tuple<float, N>隐式实例化。但是隐式实例化与显式实例化有两个重要区别

  1. 它们不会实例化所有成员定义(只实例化那些立即需要的成员定义)。其他定义只有在使用时才会实例化
  2. 所用成员定义的隐式实例化不能用作其他翻译单元的定义源

对于后者,由于我不知道原因,我只引用规范

非导出模板必须在每个隐式实例化的翻译单元中定义(14.7.1),除非在某个翻译单元中显式实例化了相应的专门化(14.7.2);不需要进行诊断。

这可能与链接器的复杂性有关,因为同一模板的隐式实例化可能在多个翻译单元中发生多次,因此需要特殊处理。显式实例化和非内联函数不能。

您可以使用一些模板魔术来强制实例化:

namespace {
    template <unsigned N>
    struct Instantiator {
        void instantiate_members(const Tuple<float,N>& tuple, Instantiator<N-1>) {
            // use **all** member functions here
            // so that they get instantiated
        }
    template <>
    struct Instantiator<0> {}
}

然后实例化这个模板:

template class Instantiator<20>;

不幸的是,这在维护方面并不好,因为您需要使instantiate_members函数保持最新。您需要确保所有成员都被调用,包括所有各种重载。

避免模板链接错误的正确方法是将模板定义放在每个使用它们的TU中。通常,头文件最适合用于此目的。使用这样的显式实例化往好里说是半有效的,往坏里说只是令人困惑。