型変換演算子を使って戻り値のオーバーロード風を実現
C++テンプレートテクニック 9-3
戻り値のみでは通常オーバーロードはできません。
#include <iostream> using std::cout; using std::endl; class CClassA {}; class CClassB {}; CClassA foo() { return CClassA(); } CClassB foo() { return CClassB(); } int main () { CClassA a = foo(); CClassB b = foo(); return 0; }
$ cl /W4 /EHsc main.cpp Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. main.cpp main.cpp(8) : error C2556: 'CClassB foo(void)' : オーバーロード関数は、'CClassA foo(void)' と戻り値の型のみが異なります。 main.cpp(7) : 'foo' の宣言を確認してください。 main.cpp(8) : error C2371: 'foo' : 再定義されています。異なる基本型です。 main.cpp(7) : 'foo' の宣言を確認してください。 main.cpp(11) : error C3861: 'foo': 識別子が見つかりませんでした main.cpp(11) : error C2440: '初期化中' : 'CClassA (__cdecl *)(void)' から 'CClassA' に変換できません。 コンストラクタはソース型を持てません、またはコンストラクタのオーバーロードの解決があいまいです。 main.cpp(12) : error C3861: 'foo': 識別子が見つかりませんでした main.cpp(12) : error C2440: '初期化中' : 'CClassA (__cdecl *)(void)' から 'CClassB' に変換できません。 コンストラクタはソース型を持てません、またはコンストラクタのオーバーロードの解決があいまいです。
このように、戻り値は省略可能なのでオーバーロードできません。
しかし、型変換演算子をうまく利用すればオーバーロードのようなことが可能となります。
#include <iostream> using std::cout; using std::endl; class CClassA {}; class CClassB {}; CClassA func_a() { return CClassA(); } CClassB func_b() { return CClassB(); } class X { public: operator CClassA() { return func_a(); } operator CClassB() { return func_b(); } }; X foo () { return X(); } int main () { CClassA a = foo(); CClassB b = foo(); return 0; }
func_aとfunc_bという戻り値の型が違う別々の関数を定義し、Xクラスの型変換演算子を利用すればオーバーロードが実現できます。
ただコード量が結構増えるのでもっと簡略化できれば良さそうなんですが。