戻り値の型だけが違うオーバーロード関数を作る方法

※開発環境はVC2010です。
C++では関数のオーバーロードは関数名が同じで引数が異なることが条件です。そのため同じ関数名で戻り値の型だけが違う関数を作るとエラーになってしまいます。

static int GetPi() { return 3; }
static double GetPi() { return 3.14; }

//  error C2556: 'double GetPi(void)' : オーバーロード関数は、
// 'int GetPi(void)' と戻り値の型のみが異なります。

しかし、テンプレートを使えば同じ関数名の戻り値の型が違う関数を作ることができます(そのように見せることができるだけですが...)。

template <typename T>
static T GetPi()        {};

// int型の特殊化
template <>
static int GetPi<int>()      { return 3; }

// double型の特殊化
template <>
static double GetPi<int>()   { return 3.14; }

通常テンプレートは型は違うけど処理の内容が同じときに利用しますが、特定の型だけ別の処理ができるようになっています。例えばSwapという関数はテンプレートで書くのにうってつけですが、自分の作ったクラスの時だけは普通にスワップするんじゃなくて独自の処理にしたい、そういうときに利用します。これをテンプレートの特殊化といいます。今回はそれを利用してintとdoubleの処理を特殊化して別の処理として扱うようにします。
今回作成した関数の使い方は下記に示すように明示的に型を指定しなければなりません。その点で厳密には同じ関数名とは言えませんが、一応これで同じ関数名で戻り値の型の違う関数を作ることができます。

int i = GetPi<int>();
double d = GetPi<double>();

もしここで特殊化していない型を指定するとエラーが発生します。それは最初に定義してあるGetPiを展開しようとしますがなにも返さないからです。

unsigned int s = GetPi<unsigned int>();

// error C4716: 'GetPi<unsigned int>' : 値を返さなければいけません

実際にはint用の関数とdouble用の関数を作ってしまえばそれでよいのであまり意味はありませんが、単にコードの見た目の良さを追求した結果です。