3

をオーバーロードする列挙型 type がありoperator>>ます。

std::istream& operator >>(std::istream &is,MyEnum& enumVar)
{
  int intVal;
  is>>intVal;
  enumVar = intVal;
  return is;
}

将来のすべての列挙型に対してこのコードを作成しないようにする方法、つまり、すべての列挙型に適用できるように関数を作成する方法を教えてください。

4

1 に答える 1

5

オペレーターをテンプレートにし、テンプレート パラメーターが列挙型の場合にのみ有効にします ( を使用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
于 2013-04-02T10:02:07.463 に答える