重载运算符“>>”上的 bad_lexical_cast 异常

Posted

技术标签:

【中文标题】重载运算符“>>”上的 bad_lexical_cast 异常【英文标题】:bad_lexical_cast exception on overloaded operator ">>" 【发布时间】:2014-08-17 13:48:18 【问题描述】:

我为枚举重载了运算符“>>”:

#include <iostream>
#include <boost/lexical_cast.hpp>


using namespace std;

enum MyEnum
    
        ONE = 0,
        TWO, 
        TREE,
        MAX
    ;

const char* MyEnumString[MAX] =

    "ONE"
    ,"TWO"
    ,"THREE"
;

istream& operator>>(istream& is, MyEnum& myEnum)

    string value;
    is >> value;

    myEnum = ONE;

    for (int i=0; i < MAX; i++)
    
        if (!value.compare(MyEnumString[i]))
        
            myEnum = static_cast<MyEnum>(i);
            return is;
        
    

    return is;


int main()

   cout << "Hello World" << endl; 
   boost::lexical_cast<MyEnum>(""); //Throws exception. 

   return 0;

我得到的输出:

你好世界 在抛出一个实例后调用终止 'boost::exception_detail::clone_impl

' what(): bad lexical cast: 源类型值不能被解释为目标

从 lexical_cast_39.hpp (1155) 抛出异常:

if (interpreter >> result)

该运算符适用于除空字符串之外的每个值。从运算符返回的输入流与一开始的输入流相同。

对于此类问题,可接受的方法是什么? 谢谢!

【问题讨论】:

【参考方案1】:

问题是您告诉lexical_cast 将空字符串转换为MyEnum。你希望它做什么?不能返回真正的值,所以异常是正确的。

更详细的细分:lexical_cast 正在获取输入的空字符串,并从该值创建一个输入流。然后将其传递给您的operator&gt;&gt;。当您执行is &gt;&gt; value; 时,它会在流上设置eof 标志(因为它试图读取字符串,并且没有剩余数据。

在您的函数返回后,它会完成if ( interpreter &gt;&gt; result ),它主要检查流是否仍处于良好状态。由于不是(由于前面的eof 位),因此它失败并出现异常。

如果您希望将空字符串解释为特定值,则必须在返回之前从流中清除错误标志。就个人而言,我不会这样做,因为它会限制输入运算符在其他情况下的有用性。如果我需要这个功能,我很可能会在调用 lexical_cast 之前检查空字符串。

【讨论】:

感谢您的解释。我只是没有得到,就运算符的功能而言,将映射到默认 ONE 的随机字符串值与也应该映射到 ONE 的空字符串值之间有什么区别。除非我们将空字符串作为一个概念称为“无值”,否则您应该抛出异常是对的。 不同之处在于,随机的非空文本可以成功读入字符串,而空文本会导致输入操作失败。实际上,您的 operator>> 实现应该执行 if (!(is &gt;&gt; value)) return is; 以正确处理输入错误。默认为任何值都会违反最小意外原则,因为没有其他类型具有类似的行为。

以上是关于重载运算符“>>”上的 bad_lexical_cast 异常的主要内容,如果未能解决你的问题,请参考以下文章

C++ 重载运算符 '>>'

不能重载 Raku 中的 >> 运算符

无法在 C++ 中重载流提取运算符 (>>)

使用重载的 >> 运算符调用 CPP 构造函数

C++ 作业 - 使用动态数组重载 >> 运算符

使用重载输入流运算符读取带字符串的文件>>