2011-06-18 150 views
1

如果我有一类叫做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>; 
+1

'AllTuples :: x'也应该是'AllTuples',而不是'Tuple'。 – Xeo

+0

@Xeo:谢谢你指出,固定(虽然仍不能解决原来的问题) – Samaursa

回答

4

对不起你的运气了。除非使用预处理器元编程库(boost.pp),否则无法将其自动化。不适用于模板元编程。

你在那里制作的是隐式实例化Tuple<float, N>。但是隐式实例与外部实例有两个重要的区别

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

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

非导出的模板必须在每个翻译单元,其中它是隐式实例化(14.7.1)来定义,除非相应的专业化明确实例化(14.7.2)在一些翻译单元;不需要诊断。

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

+0

''这可能与链接器的复杂性有关,因为同一个模板的隐式实例可能在多个翻译单元中出现多次,所以它们需要特殊的处理,显式实例化和非内联函数不能。“'为什么在'Tuple.cpp'中键入'template Tuple ',可以在多个翻译单元中使用,而不会出现链接错误?请原谅我缺乏知识,因为我对模板比较陌生。 – Samaursa

+0

@Samaursa如果你在'Tuple.cpp'和'List.cpp'中键入'template Tuple ;',那么你的程序不合格(不需要诊断)。对于给定的类,显式实例化只能出现一次。据我了解,明确实例化的函数在GCC上有很强的连接,所以这样一个不合格的程序会产生链接错误,因为两个强连接符号不能连接在一起。隐式实例化的函数具有弱连接性,这意味着编译器将丢弃除它们中的一个版本以外的所有其他所有函数。 –

+0

我可能误解了你的评论。我不是在'List.cpp'中输入它......?我目前正在做的是这里所建议的:http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13。问题中提到的问题是我有很多'模板元组'我想要支持的最大范围,并且我想尽可能避免输入所有这些。 – Samaursa

1

你可以使用一些模板魔法来迫使该实例:

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函数是最新的。您需要确保全部成员被调用,包括所有各种重载。

+0

+1不错,虽然我仍然不同意这样做的原因 –

+1

这将实例化类,但不是成员方法 –

+0

@DavidRodríguez - dribeas:这确实是什么情况,为什么它不工作为了我。 – Samaursa

0

避免模板链接错误的正确方法是将模板定义放置在您使用它们的每个TU中。通常,头文件最适合于此目的。使用这样的显式实例最多是半有效的,最坏的情况是该死的混淆。

+0

我同意,不幸的是我有我强制要求我不能发布源代码:( – Samaursa

+0

@Samarusa:一小部分代码生成可能在这里工作,我认为你的makefile中的三行bash脚本会生成一个头文件文件包含第一个代码块,对于你选择的任何数字,但是你肯定会有可移植性问题 –

+0

@Samaursa:源代码是可以简单分解的 –