I have the following method:
template<typename CharT, typename Traits, typename Alloc>
auto getline_n(std::basic_istream<CharT, Traits>& in, std::basic_string<CharT, Traits, Alloc>& str, std::streamsize n) -> decltype(in)
Full version of the this method included at the bottom.
I need to be able to convert a std::ifstream to a std::basic_istream<CharT, Traits>& so I can pass it to this method.
Here is what the calling code might look like:
std::ifstream pipe2;
pipe2 = std::ifstream {};
pipe2.open("/<pathToNamedPipe>");
std::basic_istream<char,???> s = pipe2;
std::string line{};
getline_n(s, line, 50);
Not really clear on Traits and what they are for std::basic_istream? See ??? above.
Example 2 (because people were asking why I don't just pass pipe2 which was the first thing tried BTW) as in:
std::ifstream pipe2;
pipe2 = std::ifstream {};
pipe2.open("/<pathToNamedPipe>");
std::string line{};
getline_n(pipe2, line, 50);
then I get a Xcode compiler error:
"'std::ifstream' (aka 'basic_ifstream<char>') to 'char **'."
That is why I am trying to convert it to std::basic_istream<char,???>.
Here is the complete method I want to call:
template<typename CharT, typename Traits, typename Alloc>
auto getline_n(std::basic_istream<CharT, Traits>& in, std::basic_string<CharT, Traits, Alloc>& str, std::streamsize n) -> decltype(in) {
std::ios_base::iostate state = std::ios_base::goodbit;
bool extracted = false;
const typename std::basic_istream<CharT, Traits>::sentry s(in, true);
if(s) {
try {
str.erase();
typename Traits::int_type ch = in.rdbuf()->sgetc();
for(; ; ch = in.rdbuf()->snextc()) {
if(Traits::eq_int_type(ch, Traits::eof())) {
// eof spotted, quit
state |= std::ios_base::eofbit;
break;
}
else if(str.size() == n) {
// maximum number of characters met, quit
extracted = true;
in.rdbuf()->sbumpc();
break;
}
else if(str.max_size() <= str.size()) {
// string too big
state |= std::ios_base::failbit;
break;
}
else {
// character valid
str += Traits::to_char_type(ch);
extracted = true;
}
}
}
catch(...) {
in.setstate(std::ios_base::badbit);
}
}
if(!extracted) {
state |= std::ios_base::failbit;
}
in.setstate(state);
return in;
}
It originates from this SO post:
How to safely read a line from an std::istream?
The background for this question is that std::getline has a bug that I'm attempting to work around with a custom getline (getline_n) as discussed in this SO Post:
Why does the buffering of std::ifstream "break" std::getline when using LLVM?