【问题标题】:is recursive explicit template instantiation possible?递归显式模板实例化可能吗?
【发布时间】:2011-09-12 23:15:21
【问题描述】:

给定一个类似的模板

template<int dim> class Point { ... };

这个模板可以像这样显式地实例化

template class Point<0>;
template class Point<1>;
template class Point<2>;
template class Point<3>;

我不想像上面那样单独实例化每个模板,我想用一个调用递归地实例化它们

template class RecursiveInstantiate<Point, 3>;

RecursiveInstantiate&lt;T, i&gt; 将实例化 T&lt;i&gt;T&lt;i-1&gt;、...、T&lt;0&gt;。是否有可能创建这样一个类RecursiveInstantiate?如果不可能,您知道使用预处理器的方法吗?

事实上,对于具有多个模板参数的类(例如Node&lt;int i1,int i2,int i3&gt;),对于 {0,1,2,3} 中的 i1,i2,i3 的所有组合,我很感兴趣。但我希望能够自己完成第二部分。

感谢任何建议,以及解释为什么我想要实现的目标是不可能的。


更新:到目前为止感谢您的 cmets。我现在更清楚地看到了问题的真正所在。线

template class Point<3>;

实例化模板并将其符号导出到目标文件。表单的实例化

template class RecursiveInstantiate<Point, 3>;

可以实例化类class Point&lt;3&gt;class Point&lt;2&gt;、...。但显然这只发生在本地。模板不会导出到目标文件。也许我将不得不寻找使用预处理器的解决方案。

正如我现在看到的那样,我一开始没有足够准确地提出我的问题,我感谢您的回答和选择的正确答案。

注意:我正在使用 g++/clang 作为编译器的 linux 上尝试这个。

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    你可以做一个小实例化器类:

    template <unsigned int N> struct Instantiator
    {
      Point<N> p;
      Instantiator<N-1> i;
    };
    
    template <> struct Instantiator<0>
    {
      Point<0> p;
    };
    

    然后简单地添加一个显式实例化:template struct Instantiator&lt;81&gt;;

    您可以按字典顺序将此想法扩展到任意数量的整数参数。


    正如@Georg 所说,让我们让它通用:

    template <template <unsigned int> class T, unsigned int N> struct Instantiator
    {
      T<N> t;
      Instantiator<T, N-1> i;
    };
    
    template <template <unsigned int> class T> struct Instantiator<T, 0>
    {
      T<0> t;
    };
    
    template struct Instantiator<Point, 82>;
    

    【讨论】:

    • 让它template&lt;class T, unsigned N&gt; struct I { T&lt;N&gt; p; I&lt;T, N-1&gt;; }; ...。此外,使用元算法和元函数可以避免硬编码参数计数(请参阅 Boost.MPL 的作用)。
    • 这个解决方案看起来很不错,我真的很喜欢你的通用解决方案。我仍然很难让它发挥作用。该方法编译得很好,是的,但不知何故 Point&lt;0&gt; 的符号不会导出到目标文件中,这就是代码 template class Point&lt;0&gt;; 将要做的事情。明天我将不得不进一步调查。我在 Linux 上使用 g++/clang,但我不确定这是否特定于我的架构。
    • 我不确定这是否真的有效。我尝试过的任何变体实际上都不会在目标文件中产生任何内容。
    【解决方案2】:

    你可以这样做:

    template<int dim> struct Point {
        static const int val = dim;
        Point<dim - 1> p;
    };
    
    template<> struct Point<0> { ... };
    

    当模板参数为0 时,它会为模板参数创建一个模板特化,因此递归停止在那里,并且当您像这样实例化一个时:

    Point<4>
    

    它从Point&lt;4&gt; 向下实例化到Point&lt;0&gt;。然后就可以了

    Point<4>::val
    

    访问那个特定的值。

    【讨论】:

    • 不过,这需要修改并控制Point 的定义。
    • @Kerrek 这个概念可以很容易地扩展使用,无需修改Point
    • 这种方法对我不起作用。如果我实例化template class Point&lt;4&gt;;,那么只有Point&lt;4&gt; 的符号被导出到目标文件中,而不是其他符号,尽管编译器确实正确执行了递归。
    猜你喜欢
    • 2011-11-15
    • 1970-01-01
    • 2021-11-25
    • 2014-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-13
    • 1970-01-01
    相关资源
    最近更新 更多