假设我有一个类包含一个大的数量的其他类声明。是否有可能以某种方式传播这些代码的成本,以便嵌套类型的编译时内存消耗不会以二次方式增长?如果需要的话,我愿意在编译时间上受到打击,并且如果这是一个选项,我们很乐意将其分解到不同的翻译单元中。如何减少大型模板的编译时内存占用量?
要尝试,并拿出一个解决的办法,我写了下面的程序,它说明了导致这些井喷样的代码的简化版本:
// Add T to the list of args of SeqWithArgs N number of times:
template <int N, typename T, typename SeqWithArgs>
struct Append;
template <int N, typename T, template <typename...> class Seq, typename... Args>
struct Append<N, T, Seq<Args...>>
{
using type = typename Append<N-1, T, Seq<Args..., T>>::type;
};
template <typename T, template<typename...> class Seq, typename... Args>
struct Append<0, T, Seq<Args...>>
{
using type = Seq<Args...>;
};
static constexpr const int N = 10;
// Tuple containing N instances of int
using Small = typename Append<N, int, std::tuple<>>::type;
// Tuple containing N instances of Small
using Big = typename Append<N, Small, std::tuple<>>::type;
// Tuple containing N instances of Big
using Huge = typename Append<N, Big, std::tuple<>>::type;
int main()
{
Huge h;
return 0;
}
作为righly通过指出雅克,这些操作是非常低效的。但是,在修改这些代码的实际版本中,需要对代码进行基本的重构。
我变化了N
从10到70,并得到了这个结果编译我的程序使用GCC 4.8.1
。我还运行time -v make
以获得峰值驻留内存使用量。下面是仅使用默认的标志结果:
这个结果似乎它没有形状的,因为过多的对我来说,(预计是O(N^3),似乎遵循形状) ,但由于数量巨大。它看起来很像Small
正在扩大对每实例化大,反过来大被扩大了的巨大每一个实例。在模板较少的代码中,通常会使用关键字extern
来声明某种类型的泛型,并因此会避免这种“嵌套扩展”,但这些是类型而不是值;这种构造是否存在类似的东西?
这是什么井喷内存的原因,我能做些什么来减少这种内存占用没有改变Small
,Big
和Huge
类型?
好的问题总的来说。但是,您将编制成本函数称为“指数”和“O(n³)”。我敢说这些并不完全一样...... – 5gon12eder 2014-10-17 00:16:08
对于那些不熟悉模板的人,能否用文字解释代码的作用? – 2014-10-17 00:16:59
@NeilKirk该代码构造一个包含N个int类型元素的元组。然后它构造一个这种类型的N个元素的元组。然后它构造一个包含*那个*类型的N个元素的元组。 (即,以三的顺序嵌套,导致N^3个元素)。现在的问题基本上是为什么编译器在这个数字(N^3)中有一个线性计算努力,而不是在每个常量时间内重复使用以前计算的类型,这会导致线性时间总体复杂性(以N为单位) – leemes 2014-10-17 00:19:36