1

The program built from this code:

#include <fstream>
using std::basic_ifstream;

#include <ios>
using std::streamsize;

#include <ZenLib/Conf.h>
using ZenLib::int8u;

int main() {
#define charT int8u
#define T basic_ifstream<charT>
    T ifs ("/proc/cpuinfo", T::in | T::binary);
#undef T
    streamsize const bufsize (4096);
    charT buf[bufsize];
#undef charT
    return !ifs.read(buf, bufsize).gcount();
}

... returns 1.

So std::basic_ifstream<ZenLib::int8u>::read() could not extract any byte from /proc/cpuinfo.

Am I doing anything wrong?

  • Can you synthesize a simple, self-contained example that doesn't require chasing through multiple macros? – Kerrek SB Nov 02 '14 at 16:05
  • The streams are designed to be used with character types as template parameters, not integers. – Galik Nov 02 '14 at 16:07
  • Streams only support the character types `char` and `wchar_t`. This isn't guaranteed to work for different character types because of a lack of a specialized code conversion facet. – David G Nov 02 '14 at 16:07

2 Answers2

2

The stream libraries are designed to be used with the character types such as char and wchar_t, not integers:

C++11 standard: 27.2.2

  1. In the classes of Clause 27, a template formal parameter with name charT represents a member of the set of types containing char, wchar_t, and any other implementation-defined character types that satisfy the requirements for a character on which any of the iostream components can be instantiated.

Maybe start from this:

int main()
{
    std::ifstream ifs("/proc/cpuinfo", std::ios::binary);
    std::cout << ifs.rdbuf();
}
Galik
  • 47,303
  • 4
  • 80
  • 117
2

Intantiating std::char_traits for anything but char or wchar_t is undefined behavior (And I suspect that your charT is unsigned char, not char.) If you want to use a different type for characters, you'll have to define a new traits class; for std::istream anf std::ostream, you'll also have to define a number of facets for the type as well.

The question is what you want to do. In your example, you only call std::istream::read. If this is the case, the simplest solution is probably to just drop down to the system level functions. These probably want a char* for there buffer as well, but a reinterpret_cast from unsigned char* will work. You can do this for std::istream<char>::read as well, but if you have an std::istream, there's a definite possibility that some formatted input will creap in, and that will interpret the characters before you can get your reinterpret_cast in.

James Kanze
  • 150,581
  • 18
  • 184
  • 329