C++ では仮引数の型が全て同じで返却値だけ型が違うような関数をオーバーロードすることは出来ません。 以下のようなオーバーロードを試みるとエラーになることが確認できると思います。
constexpr int one(void) {
return 1;
}
constexpr char one(void) {
return '1';
}
どうしても返却値だけ型が違う関数を定義したいのならばテンプレート (特殊化) を使う方法があります。
template<class T> constexpr T one(void);
template<> constexpr int one(void) {
return 1;
}
template<> constexpr char one(void) {
return '1';
}
ところが、 C++ の関数テンプレートの型推論は__引数の型__を基にしておこなうので、引数の型が同じ (今回の例では引数を受け取らない) 関数テンプレートでは推論できません。 以下のように、呼出すときに型を陽に指定する必要があります。
#include <iostream>
int main(void) {
constexpr int a=one<int>();
constexpr char b=one<char>();
std::cout << a << b <<std::endl;
return 0;
}
関数呼出しの際にどうにかして型を書かずに済ます方法はないかと考えたとき、型変換演算子を活用するという方法を思い付きました。
class one {
public:
constexpr one(void) {}
template<class T> constexpr operator T(void);
};
template<> constexpr one::operator int(void) {
return 1;
}
template<> constexpr one::operator char(void) {
return '1';
}
#include <iostream>
int main(void) {
constexpr int a=one();
constexpr char b=one();
std::cout << a << b <<std::endl;
return 0;
}
型変換の時点で実際の処理を発生させるので、副作用を伴う関数では注意深く扱う必要がありますが、そうでない場合には有用な場面もあるのではないでしょうか。