gpt4 book ai didi

c++ - std::istream 提取设置 failbit 没有明显原因

转载 作者:行者123 更新时间:2023-11-30 04:32:56 25 4
gpt4 key购买 nike

我正在创建一个原始类型包装器,它可以使用 boost::lexical_cast 从字符串设置它的值。它工作正常,但由于某种原因 std::istream 提取运算符设置了 failbit。以下程序打印:

123.45
异常:ios_base::failbit 设置

但是,如果您注释掉“inStream.exceptions( ...”行,它会工作并打印:

123.45
123.45

无论您是否使用 unicode 进行编译,或者如果您使用 int 或 float 作为 ValueType,failbit 都会在任何情况下设置。

#include <conio.h>
#include <exception>
#include <iostream>
#include <string>
#include <tchar.h>

#include <boost/lexical_cast.hpp>

#if defined(UNICODE) || defined(_UNICODE)
typedef std::wstring StringType;
typedef std::wistream IStreamType;
#else
typedef std::string StringType;
typedef std::istream IStreamType;
#endif


#if 1 // Use float
typedef float ValueType;
#define VALUE_STRING _T("123.45")
#else // Use int
typedef int ValueType;
#define VALUE_STRING _T("123")
#endif


struct Castable {
ValueType m_val;
};

inline IStreamType& operator>> ( IStreamType& inStream, Castable& castable )
{
inStream.exceptions( IStreamType::failbit | IStreamType::badbit );
inStream >> castable.m_val;
return inStream;
}


int _tmain(int argc, _TCHAR* argv[])
{
try{
StringType sVal = VALUE_STRING;

ValueType val;
val = boost::lexical_cast<ValueType>(sVal);
std::cout << val << std::endl;

Castable cst;
cst = boost::lexical_cast<Castable>(sVal);
std::cout << cst.m_val << std::endl;

}catch( std::exception& ex ){
std::cout << "EXCEPTION: " << ex.what() << std::endl;
}

_getch();
return 0;
}

为什么 std::istream 会认为出了问题?

最佳答案

其中一个原因可能是 lexical_cast 的实现可能故意尝试导致某些流失败,以检查所有输入文本是否已被消耗。例如,一个简单的实现可能如下所示:

template <typename Target>
Target lexical_cast(const string& s) {
/* Insert the string into a stringstream to use extraction. */
std::stringstream converter(s);

/* Pull out an object of type Target, failing if we can't. */
Target result;
if (!(converter >> result)) throw bad_lexical_cast();

/* To confirm that we read everything out of the stream, try pulling out a
* single character. If we can do this, then there is something left in the
* stream that wasn't picked up earlier and the input was malformed.
*/
char ch;
if (converter >> ch) throw bad_lexical_cast();

return result;
}

这里的想法是最后的检查试图打破流以查看是否遗留了一些东西。如果启用异常,这会将本应是可使用 failbit 检测到的正常流故障变为异常,这是代码未预料到的。

不过,更一般地说,您不应该在提取例程内设置流设置。这取决于调用者。否则,无论您在调用提取例程之前尝试对流做什么,该例程都会覆盖您的首选项。毕竟,如果我显式禁用异常,然后因为你在 operator >> 中重新打开它们而无论如何都会发生异常,那就太糟糕了。

希望这对您有所帮助!

关于c++ - std::istream 提取设置 failbit 没有明显原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7340946/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com