Tuesday 29 April 2014

Exiting recursive function templates without using helper class templates and partial specialisation

Contrived examples follow, but they serve to illustrate partial specialisation of class templates vs exiting recursive function templates using a branch.

The old way: use a helper class template, partially specialise it with the recursion exit case, and call a static function on this class template from a function template:

#include <iostream>

// helper class template
template<typename T, unsigned idx>
struct foo_impl
{
    static void fn(T t)
    {
        std::cout << t << " " << idx << std::endl;
        foo_impl<T, idx - 1>::fn(t); // recursively call fn
    }
};

// partial specialisation of helper class template for exit case
template<typename T>
struct foo_impl<T, 0>
{
    static void fn(T) {} // do nothing exit case
};

// function template which uses helper class templates
template<unsigned idx, typename T>
void foo(T t)
{
    foo_impl<T, idx>::fn(t);
}

int main()
{
    foo<5>("Hello world");
    return 0;
}

The new way: have the special case branch in the function template itself, and recursively call the function template from itself.

To prevent the compiler from barfing when instantiating the recursive path, the trick is to recursively call the function template with the same parameters for the special case. Even though this code path will never actually execute, it is needed so the compiler can parse the template.

#include <iostream>

template<unsigned idx, typename T>
void foo(T t)
{
    if (idx == 0) // special exit case
        return;
    std::cout << t << " " << idx << std::endl;

    // recursively call the function
    foo<idx - (idx ? 1 : 0)>(t); // note recursion returns itself in special exit case (code path will actually never be reached)
}

int main()
{
    foo<5>("Hello world");
    return 0;
}


Friday 11 April 2014

Create a local git repo, a remote github repo and sync them from the command line

Create a local repo

follow the instructions here.

Install hub

# install dependencies
sudo apt-get install rake

# clone repo
cd /tmp
git clone https://github.com/github/hub.git

# install hub
cd hub
sudo rake install prefix=/usr/local

# alias git to hub
echo 'alias git=hub' >> ~/.bashrc
. !$

# check it works
git version
# expected output:
# git version 1.8.3.2
# hub version 1.12.0-6-g8150ddb

Create a remote repo on github

create a repo with the name of the current directory
git create -d "My description" 

# push to github
git push origin master