use*_*358 -3 c++ types type-conversion ifstream uint8t
$ file testfile.txt\ntestfile.txt: ASCII text\n\n$ cat testfile.txt \naaaabbbbccddef\n\n#include <iostream>\n#include <fstream>\n#include <string>\n#include <cstdint>\ntypedef uint8_t byte; // <-------- interesting\ntypedef std::basic_ifstream<byte> FileStreamT;\nstatic const std::string FILENAME = "testfile.txt";\nint main(){\n FileStreamT file(FILENAME, std::ifstream::in | std::ios::binary);\n if(!file.is_open())\n std::cout << "COULD NOT OPEN FILE" << std::endl;\n else{\n FileStreamT::char_type buff;\n file.read(&buff,1);\n std::cout << (SOMECAST)buff; // <------- interesting\n }\n std::cout << "done" << std::endl;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n根据 typedef 中的内容以及它转换为(或未转换)的内容,它会执行各种愚蠢的操作。
\n\n它恰好适用于“typedef char”并且没有强制转换。(如预期,转换为 int 时为 97)
\n\nuint8_t 和 int8_t 都会打印
\n\n没有演员就什么都没有
转换为 char 或 unsigned char 时没有任何内容
当转换为 int 或 unsigned 时为 8(尽管 ASCII \'a\' 应为 97)
我以某种方式设法打印了“\xef\xbf\xbd”字符,但忘记了它是哪种情况。
\n\n为什么我会得到这些奇怪的结果?
\n\n从给出的答案中得出的结论:仅使用 char (或标准也提到的宽字符之一)实例化流,否则您不会收到编译器警告和静默失败
\n\n令人遗憾的是,该标准保证了这些事情
\n\n的声明template std::basic_ifstream
是:
template< \n class CharT, \n class Traits = std::char_traits<CharT>\n> class basic_ifstream;\n
Run Code Online (Sandbox Code Playgroud)\n\nC++03 标准 (21.1/1) 要求库定义= ,std::char_traits<CharT>
的特化。CharT
char
wchar_t
C++11 标准 (C++11 21.2/1) 要求库定义= 、、、std::char_traits<CharT>
的特化。CharT
char
char16_t
char32_t
wchar_t
如果您实例化时不std::basic_ifstream<Other>
使用Other
您正在编译的标准指定的 2[4] 种类型之一,则行为将是未定义的,除非您自己\n根据my_char_traits<Other>
需要进行定义,然后实例化\n std::basic_ifstream<Other,my_char_traits<Other>>
。
继续回应OP的评论。
\n\n请求std::char_traits<Other>
不会引发模板实例化\n错误:定义模板是为了可以对其进行专门化,但是\n默认(非专门化)实例化很可能对于\n甚至对于任何给定的都是错误的,其中错误的方法不满足\n标准对每个 C++03 \xc2\xa7 21.1.1/C++11 \xc2\xa7 21.2.1 的字符特征类的要求。Other
CharT
您怀疑 typedef 可能会阻碍为 -ed 类型选择模板专门化,即和是基本字符类型的 typedef,typedef
这一事实可能会导致与 不同,其中FCT是别名基本字符字符类型。uint8_t
int8_t
std::basic_ifstream<byte>
std::basic_ifstream<FCT>
忘记那个怀疑吧。typedef
是透明的。看来您相信typedef 之一并且int8_t
必须uint8_t
是char
,在这种情况下 - 除非 typedef 以某种方式干扰模板解析 -basic_ifstream
您测试过的任何行为不当的实例都必须是std::basic_ifstream<char>
但事实上它typedef char byte
是无害的呢?int8_t
认为 \或uint8_t
=都不正确的信念char
。你会发现\nis 是 whileint8_t
的别名,是 的别名。\n但是 和都不是同一类型:signed char
uint8_t
unsigned char
signed char
unsigned char
char
C++03/11\xc2\xa7 3.9.1/1
\n\n\n\n\n普通 char、signed char 和 unsigned char 是三种不同的类型
\n
因此char_traits<int8_t>
, 和char_traits<uint8_t>
都是默认的、\n非专业化的模板实例char_traits
,你\n无权期望它们满足\n标准的字符特征要求。
您没有发现任何不当行为的一个测试用例是byte
= char
。\n那是因为char_traits<char>
是库提供的\n标准专业化。
您观察到的所有不当行为与\n您已替换的类型之间的联系SOMECAST
:
std::cout << (SOMECAST)buff; // <------- interesting\n
Run Code Online (Sandbox Code Playgroud)\n\n没有。由于您的测试文件包含 ASCII 文本, \n这是标准保证\n读取它basic_ifstream<char>
的唯一实例。basic_ifstream
如果您在程序中使用读取该文件,typedef char byte
\n那么您所说的替换的任何转换都不会产生意外的\n结果:SOMECAST
= char
orunsigned char
将输出a
,并且\n SOMECAST
= int
orunsigned int
将输出97
。
所有不当行为都源于basic_ifstream<CharT>
使用CharT
标准不保证的某种类型进行实例化。