为所有枚举类型重载运算符>>

3
我有一个枚举类型,我重载了operator>>运算符。
std::istream& operator >>(std::istream &is,MyEnum& enumVar)
{
  int intVal;
  is>>intVal;
  enumVar = intVal;
  return is;
}

如何避免为所有未来的枚举类型编写此代码,即如何编写函数使其适用于所有枚举类型?

你可以使用“模板”来实现方法的通用性,但是你需要使用约束机制来确保只有你的枚举类型被接受为参数。不幸的是,“约束”在C++中并不容易被支持。 - bash.d
我知道我可以使用模板和boost::enable_if来实现某些功能,但我真的不太理解它是如何工作的。 - user152508
http://www.boost.org/doc/libs/1_53_0/libs/utility/enable_if.html - user152508
有点难...我不知道boost,抱歉... - bash.d
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模板成对出现 - 当条件(第一个模板参数)为真时,具有第二个模板参数的成员typedef为type,而当条件为假时则没有该typedef。具有false条件的模板实例化是无效的,因为成员typedef不存在。此类实例化随后(而不是成为硬编译器错误)从重载集中丢弃以进行后续重载分辨率。还要阅读有关SFINAE的信息。
编辑:boost的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

谢谢。我使用boost,所以我在你的代码中用boost::替换了std::。但不幸的是,我遇到了编译器错误:error C2923: 'boost::enable_if' : 'boost::is_enum<T>::value' 不是参数“Cond”的有效模板类型参数。 - user152508
模板<typename T> typename boost::enable_if<boost::is_enum<T>::value, std::istream&>::type operator >>(std::istream &is, T& enumVar) { std::cout << "枚举\n"; int intVal; is >> intVal; enumVar = static_cast<T>(intVal); // 注意显式转换以使其合法 return is; } - user152508

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接