如何延长词法投支持枚举类型?(How can I extend a lexical cast to

2019-07-21 04:27发布

我有以下的功能,将字符串转换成数字数据类型:

template <typename T>
bool ConvertString(const std::string& theString, T& theResult)
{
    std::istringstream iss(theString);
    return !(iss >> theResult).fail();
}

这并不适用于枚举类型的工作,但是,所以我做了这样的事情:

template <typename T>
bool ConvertStringToEnum(const std::string& theString, T& theResult)
{
    std::istringstream iss(theString);
    unsigned int temp;
    const bool isValid = !(iss >> temp).fail();
    theResult = static_cast<T>(temp);
    return isValid;
}

(我在做这theString具有枚举类型的有效值的假设,我用这主要是简单的序列)

有没有一种方法来创建结合了这两种功能单一?

我打得有点与模板参数,但没有拿出任何东西; 它会只是不错不要有呼吁枚举类型的一切一个功能与其它。

谢谢

Answer 1:

你必须做两步。 发现一体型足够大的存储值。 你可以使用unsigned long ,但值可能为负。 然后,你可以使用long ,但值可以延伸到的范围unsigned long 。 所以不是一个真正的适合它所有类型。

还有一招,虽然通过使用重载决议。 就这个

template<typename T>
struct id { typedef T type; };

id<char[1]>::type &find_etype(int);
id<char[2]>::type &find_etype(unsigned int);
id<char[3]>::type &find_etype(long);
id<char[4]>::type &find_etype(unsigned long);

你可以改变它适当地覆盖也long longunsigned long long ,如果你实现了这种支持。 现在,通过枚举类型会更喜欢其中一个比所有其他的人 - 这是一个可以存储的所有值的类型。 你只需要传递sizeof返回类型的一些模板。

template<int> struct get_etype;
template<> struct get_etype<1> { typedef int type; };
template<> struct get_etype<2> { typedef unsigned int type; };
template<> struct get_etype<3> { typedef long type; };
template<> struct get_etype<4> { typedef unsigned long type; };

现在,你可以得到一个正确的类型。 你现在需要的是看到一些类型是否是一个枚举。 如何这是书中所描述做“C ++模板 - 完整的指南”,可惜是一大堆的代码。 所以,我会用升压转换器的is_enum 。 将其组合在一起,它可能看起来像

template <typename T>
typename boost::disable_if< boost::is_enum<T>, bool>::type 
ConvertString(const std::string& theString, T& theResult)
{
    std::istringstream iss(theString);
    return !(iss >> theResult).fail();
}

template <typename T>
typename boost::enable_if< boost::is_enum<T>, bool>::type 
ConvertString(const std::string& theString, T& theResult)
{
    typedef typename get_etype<sizeof find_etype(theResult)>::type 
      safe_type;

    std::istringstream iss(theString);
    safe_type temp;
    const bool isValid = !(iss >> temp).fail();
    theResult = static_cast<T>(temp);
    return isValid;
}

希望这可以帮助。



Answer 2:

而只是为了“完成”的问题,在C ++ 0x中,我们可以只是这样做:

typedef typename std::underlying_type<T>::type safe_type;

在地方约翰内斯的get_etype把戏。



文章来源: How can I extend a lexical cast to support enumerated types?