提问者:小点点

如何将std::ifstream转换为std::basic_istream<chart,traits>&?


我有以下方法:

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::ifstream转换为std::basic_istream&; 所以我可以把它传递给这个方法。

下面是调用代码的样子:

std::ifstream pipe2;
pipe2 = std::ifstream {};
pipe2.open("/<pathToNamedPipe>");
std::basic_istream<char,???> s = pipe2;
std::string line{};
getline_n(s, line, 50);

不清楚std::basic_istream的特性和它们是什么? 看到了吗??? 上面。

例2(因为人们问我为什么不通过pipe2,这是BTW首先尝试的事情),如:

std::ifstream pipe2;
pipe2 = std::ifstream {};
pipe2.open("/<pathToNamedPipe>");
std::string line{};
getline_n(pipe2, line, 50);

然后我得到一个Xcode编译器错误:

"'std::ifstream' (aka 'basic_ifstream<char>') to 'char **'."

这就是为什么我试图将其转换为std::basic_istream的原因。

下面是我要调用的完整方法:

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;
}

它源于这个SO帖子:

如何安全地从std::istream中读取一行?

这个问题的背景是,std::getline有一个bug,我正在尝试使用自定义getline(getline_n)来解决这个bug,正如这篇SO文章中所讨论的:

为什么当使用LLVM时,std::ifstream的缓冲会“中断”std::getline?


共1个答案

匿名用户

你不知道。

您的std::ifstream已经从std::basic_istream派生。

这样定义函数是为了让您可以将[引用]传递给另一种流(如果您愿意的话)。

如果程序中的其他地方没有错误,那么这段代码已经可以工作了。