🗂
C++14 で std::enable_if で fallback つきでクラスメソッドのオーバーロードしたいメモ
C++14 で, テンプレート変数を取るクラスのメソッドで, 型に応じて異なる振る舞いをしたいが, fallback(指定した型以外を処理するデフォルトメソッド) もほしい.
とりあえず std::enable_if でいけるらしいが...
enable_if で分けたいときが 3 個以上あるとき...(2 個であれば enable_if と enable_if<!> でいけるため)
テンプレートなんもわからん...
template<class T>
class Bora {
public:
// dependent type が必要なので, V をでっちあげる
template <typename V = T, std::enable_if_t<std::is_enum<V>::value, std::nullptr_t> = nullptr>
bool dora() {
std::cout << "enum type\n";
return true
}
bool dora() {
std::cout << "fallback\n";
return false;
}
}
のようにしても,
enum class Muda { Ari, Ora };
Bora<Muda> eb;
eb.dora(); // enum type を期待
Bora<int> ib;
ib.dora(); // fallback を期待
どちらも fallback のほうが呼ばれてしまいます.
fallback
fallback
解決
コメントで解決方法ご教示いただきました. ありがとうございます!
以下は元記事の記録用です.
とりあえずの解決1
ネットをあさってもあんまり情報ありません.
返り値が同じだとむりぽっそ?
返り値と引数を template 型にする必要がありますが, pxrUSD のコードで見つけた,
typename を返り値と引数で受け取るようにしてやるのがとりあえずの解決でしょうか...
// dependant type が必要なので, V をでっちあげるのは引き続き必要
template <typename V = T>
typename std::enable_if<std::is_enum<V>::value, T>::value
dora(T x) {
std::cout << "enum type\n";
return x;
}
// T dora(T x) だとエラーになるので注意
template <typename V = T>
V dora(V x) {
std::cout << "fallback\n";
return x;
}
とりあえずの解決2
にあるように, 判定をまとめるようにして, enable_if と enable_if<!> の二つになるようにする.
C++17
C++17 なら if constexpr で解決できるでしょう.
Discussion
今回の件はコンパイル自体は通っていて、オーバーロード解決の優先順位の話だと思いますので、
ダミー引数を使って優先順位を操作する方法もあります。
(数値リテラルの解釈から
intが優先される)参考
ありがとうございます!
ダミー引数必要ですが, スッキリ書けるのがいいですね. ダミー引数とってもいいようなケースではこちらで, メソッドシグネチャを変えたくないときは struct でのやり方でいきたいと思います.