をオーバーロードする列挙型 type がありoperator>>
ます。
std::istream& operator >>(std::istream &is,MyEnum& enumVar)
{
int intVal;
is>>intVal;
enumVar = intVal;
return is;
}
将来のすべての列挙型に対してこのコードを作成しないようにする方法、つまり、すべての列挙型に適用できるように関数を作成する方法を教えてください。
をオーバーロードする列挙型 type がありoperator>>
ます。
std::istream& operator >>(std::istream &is,MyEnum& enumVar)
{
int intVal;
is>>intVal;
enumVar = intVal;
return is;
}
将来のすべての列挙型に対してこのコードを作成しないようにする方法、つまり、すべての列挙型に適用できるように関数を作成する方法を教えてください。
オペレーターをテンプレートにし、テンプレート パラメーターが列挙型の場合にのみ有効にします ( を使用enable_if
):
#include <type_traits>
template<typename T>
typename std::enable_if<std::is_enum<T>::value, std::istream&>::type
operator >>(std::istream &is, T& enumVar)
{
std::cout << "enum\n"; // just to see it is this one that gets used
int intVal;
is >> intVal;
enumVar = static_cast<T>(intVal); // note the explicit cast to make it legal
return is;
}
C++11 が利用できない場合は、boost のtype_traits
ライブラリを使用できます。
どのように機能するのか正確にはわからないというコメントを見てenable_if
、ここに詳細な説明のリンクがあります。
つまり、enable_if
テンプレートはペアで提供されます。1 つは条件 (最初のテンプレート パラメーター) が true の場合に 2 番目のテンプレート パラメーターのメンバー typedef を持ち、type
条件が false の場合はその typedef を持たないテンプレートです。メンバー typedef が存在しないため、false 条件のテンプレートのインスタンス化は無効です。このようなインスタンス化は、後でオーバーロードを解決するために、(ハード コンパイラ エラーではなく) オーバーロード セットから破棄されます。SFINAEについてもお読みください。
編集: ブーストのenable_if
動作は、標準のものとは少し異なります。次のいずれかを使用します。
boost::enable_if < boost::is_enum<T>, std::istream& >::type
// ^^^^^^^^^^^^^^^^^
// expects a type
また
boost::enable_if_c < boost::is_enum<T>::value, std::istream& >::type
// ^^^^^^^^^^^^^^^^^^^^^^^^
// expects a value