假設我有一個類包含一個大的數量的其他類聲明。是否有可能以某種方式傳播這些代碼的成本,以便嵌套類型的編譯時內存消耗不會以二次方式增長?如果需要的話,我願意在編譯時間上受到打擊,並且如果這是一個選項,我們很樂意將其分解到不同的翻譯單元中。如何減少大型模板的編譯時內存佔用量?
要嘗試,並拿出一個解決的辦法,我寫了下面的程序,它說明了導致這些井噴樣的代碼的簡化版本:
// 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