http://d.puremagic.com/issues/show_bug.cgi?id=9088
Summary: static static Product: D Version: D2 Platform: All OS/Version: All Status: NEW Severity: enhancement Priority: P2 Component: DMD AssignedTo: nob...@puremagic.com ReportedBy: bearophile_h...@eml.cc --- Comment #0 from bearophile_h...@eml.cc 2012-11-27 19:20:05 PST --- Here I suggest an enhancement for D language (that is pure an addition, it should cause no breaking changes). The introduction of "static static", it roughly means "static regarding to the template". This means that if a template contains a "static static" item, it is shared among all instantiations of the template. Here are some use cases: - - - - - - - - - - - - - - Templated classes or templated structs sometimes have member functions that are meant to be shared among all the instantiations of the template. struct Foo(T) { T x; static static int sqr(int x) { return x ^^ 2; } } Here static static allows to reduce template bloat, because only one sqr() function is generated regardless the T type. Putting sqr() outside Foo is an alternative solution, but it loses the packaging given by Foo itself (despite the usefulness of universal call syntax). A third solution is to put inside Foo() just a stub function that calls an external private _sqr() function. This has both the advantage of keeping sqr() in the the namespace, and keeps the template bloat low because only very little sqr() are generated for each instantiation of Foo. But this requires parameter fowarding and increases code complexity a little. - - - - - - - - - - - - - - There are cases where templated functions need a static variable that is shared among all instantiations of the template: int foo(T)() if (is(T == char) || is(T == dchar) || is(T == wchar)) { static static dchar[] table = ['a', 'b', 'c']; static static immutable val = someHeavyCTFE(10); // uses table and val here return 0; } In this case static static is useful to save memory, because only one table is present for all instantiations of Foo. And only one val is computed, saving compilation time. An alternative design is to put both table and val outside foo(), but this adds more global names that are better kept inside foo(), just like a static variable in a function avoids names at module level. This example program computes some numbers: uint topswops(size_t nMax = 16)(in size_t n) nothrow in { assert(n > 0 && n < nMax); } body { size_t d = 0; __gshared uint[nMax] best; alias T = byte; alias Deck = T[nMax]; void trySwaps(in ref Deck deck, in uint f) nothrow { if (d > best[n]) best[n] = d; foreach_reverse (immutable i; 0 .. n) { if (deck[i] == -1 || deck[i] == i) break; if (d + best[i] <= best[n]) return; } Deck deck2 = deck; d++; uint k = 1; foreach (immutable i; 1 .. n) { k <<= 1; if (deck2[i] == -1) { if (f & k) continue; } else if (deck2[i] != i) continue; deck2[0] = cast(T)i; foreach_reverse (immutable j; 0 .. i) deck2[i - j] = deck[j]; trySwaps(deck2, f | k); } d--; } best[n] = 0; Deck deck0 = -1; deck0[0] = 0; trySwaps(deck0, 1); return best[n]; } import std.stdio; void main() { foreach (i; 1 .. 13) writefln("%2d: %d", i, topswops(i)); } To speed up the computation the n argument is now a compile-time value, and topswops() is a template: import std.stdio, std.typetuple; template Range(int start, int stop) { static if (stop <= start) alias TypeTuple!() Range; else alias TypeTuple!(Range!(start, stop - 1), stop - 1) Range; } __gshared uint[32] best; uint topswops(size_t n)() nothrow { static assert(n > 0 && n < best.length); size_t d = 0; alias T = byte; alias Deck = T[n]; void trySwaps(in ref Deck deck, in uint f) nothrow { if (d > best[n]) best[n] = d; foreach_reverse (immutable i; Range!(0, n)) { if (deck[i] == -1 || deck[i] == i) break; if (d + best[i] <= best[n]) return; } Deck deck2 = void; foreach (immutable i; Range!(0, n)) // Copy. deck2[i] = deck[i]; d++; foreach (immutable i; Range!(1, n)) { enum uint k = 1U << i; if (deck2[i] == -1) { if (f & k) continue; } else if (deck2[i] != i) continue; deck2[0] = cast(T)i; foreach_reverse (immutable j; Range!(0, i)) deck2[i - j] = deck[j]; // Reverse copy. trySwaps(deck2, f | k); } d--; } best[n] = 0; Deck deck0 = -1; deck0[0] = 0; trySwaps(deck0, 1); return best[n]; } void main() { foreach (i; Range!(1, 13)) writefln("%2d: %d", i, topswops!i()); } To work correctly this program requires a static variable "best". Once topswops() becomes a template, "best" must be moved to module scope. This is avoided by static static: ... uint topswops(size_t n)() nothrow { static assert(n > 0 && n < best.length); size_t d = 0; static static __gshared uint[32] best; ... -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------