This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Multiple Transparent Codepaths With Partial Specialization Submitted by

Here is an example of a method I've found to be quite useful when doing late optimization.
It shows how to use partial specialization together with template argument propagation for generating entire codepaths at compile time.
For instance, when you write code for 3DNow, SSE, or AltiVec, you'd only have to add an enum for each one and write down only the specialized parts.
The following code fragment shows the implementation of four functions. One of them has a 3DNow! specialization wich will be transparently used if 3DNow! is available at runtime.

    //  codepath.cxx

    #include <iostream
    using std::cerr;
    using std::endl;

    enum tFeature {
    	code3DNow,
    	codeSSE,
    	codeAltiVec,
    	codeFPU
    };

    static int detectFeature() {
    	// ...

    	// put here some code to detect the feature to be used
    	// ...
    	return code3DNow;
    }

    // some generic (FPU) functions, packaged in a struct
    // for clarity (so we can use "Method2()" instead of
    // "Method2<__codepath__()" which is a bit ugly...
    template<tFeature __code_path__
    struct example {
    	template<int N, int M
    	static inline void Method3() {
    		cerr << "Generic Method3<" << N << ", " << M << "()" << endl;
    	}
    	static inline void Method2() {
    		cerr << "Generic Method2()" << endl;
    		Method3<12, 23();
    	}
    	static inline void Method1() {
    		cerr << "Generic Method1()" << endl;
    		Method2();
    	}
    	static inline void EntryPoint() {
    		cerr << "Generic EntryPoint()" << endl;
    		Method1();
    	}
    };

    // 3DNow! version of example::Method1
    template<
    inline void example<code3DNow::Method1() {
    	cerr << "3DNow Method1()" << endl;
    	Method2();
    }

    // main
    int main(void) {
    	int codePath = detectFeature();
    	switch (codePath) {
    		case code3DNow:		example<code3DNow::EntryPoint(); break;
    		case codeSSE:		example<codeSSE::EntryPoint(); break;
    		default:		example<codeFPU::EntryPoint(); break;
    	}
    	return 0;
    }

Without 3DNow!, the output would be:

     Generic EntryPoint()
     Generic Method1()
     Generic Method2()
     Generic Method3<12, 23>()

With 3DNow!, however, it would be:

     Generic EntryPoint()
     3DNow Method1()
     Generic Method2()
     Generic Method3<12, 23>()

No test is made in EntryPoint() for choosing the 3DNow version of Method1. The trick resides in the propagation of a single template argument all along the call tree. It allow to use inlines, which is impossible with the Strategy pattern when you don't want to use slow virtual calls.
Julien Cayzac.

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.