import std.cpuid; import std.stdio; //----------------------------------------------------------------------------- // This code goes into the library const uint CPU_NO_EXT = 0, CPU_MMX = 1, CPU_SSE = 2, CPU_SSE2 = 4, CPU_SSE3 = 8; /****************************************************************************** Set initializer to first instance that matches the available hardware ******************************************************************************/ void BindMTV(alias T, E...)(ClassInfo ci, size_t offset) { uint extensions; if ( mmx ) extensions |= CPU_MMX; if ( sse ) extensions |= CPU_SSE; if ( sse2 ) extensions |= CPU_SSE2; if ( sse3 ) extensions |= CPU_SSE3; foreach ( i, ext; E ) { if ( (E[i] & extensions) == E[i] ) { *cast(void**)&ci.init[offset] = &T!(cast(uint)E[i]); return; } } throw new Exception("unsupported architecture "~std.string.toString(extensions)); } //----------------------------------------------------------------------------- // This is application code /****************************************************************************** A class with a multi-target function ******************************************************************************/ class MyMultiTargetClass { char[] function() multi_target; /// recieves the pointer to the preferred version // a template that generates multiple version for different targets char[] multi_target_mtv(uint arch)() { //pragma(target, arch) { // target independent code, e.g. vector operations return "using "~std.string.toString(arch); } } static this() { // genereate 4 different versions and activate first match BindMTV!(multi_target_mtv, CPU_SSE3, CPU_SSE2, CPU_SSE|CPU_MMX, CPU_NO_EXT)(this.classinfo, multi_target.offsetof); } } /****************************************************************************** Finally, the usage is completely opaque and there is no runtime overhead besides the detection at startup. ******************************************************************************/ void main() { MyMultiTargetClass t = new MyMultiTargetClass; writefln("%s", t.multi_target()); }