floatとdoubleをtemplateによって抽象化しようと思っています。そこで次のようなtemplate関数を考えます。

template <class T>
T plus_one(const T& num) {
  return num + T(1.0);
}

1.0 はコンパイラーではdoubleになるので、とりあえずTでキャストしていますが、キャスティングにかかる負担を削減するため、次のように実際に使うdouble, floatのために特殊化しています。

template <>
double plus_one<double>(const double& num) {
  return num + 1.0;
}
template <>
float plus_one<float>(const float& num) {
  return num + 1.0f;
}

もし、1.0f と float(1.0)がコンパイラー上で性能上の違いがなければ、上記のような特殊化はせずに元のtemplate関数だけで足りるはずです。1.0fとfloat(1.0)は違いがありますか?

そしてもし1.0fとfloat(1.0)で違いがあれば、M_PI みたいな定数をfloatで使いたい場合は仕方がなく

#define M_PI_F (3.141592f)

みたいな新たなマクロ変数を定義しなくてはならないのでしょうか?