【问题标题】:Reading from const std::vector<char> via std::istream通过 std::istream 从 const std::vector<char> 读取
【发布时间】:2014-08-04 20:14:50
【问题描述】:

我正在尝试从 const std::vector 读取到 std::istream,但我尝试的所有操作都遇到了 const 的问题。

这个版本编译完美:

#include <vector>
#include <iostream>

template<typename CharT = char, typename TraitsT = std::char_traits<CharT> >
class vectorbuf : public std::basic_streambuf<CharT, TraitsT> {
public:
    vectorbuf(std::vector<char>& v) {
        this->setg(v.data(), v.data(), v.data()+v.size());
    }
};

void doStuff(std::vector<char>& v) {
    vectorbuf<> vbuff(v);
    std::istream s(&vbuff);
}

int main(int argc, char** argv) {
    std::vector<char> v = {'a', 'b', 'c'};
    doStuff(v);
    return 0;
}

虽然这会产生错误:

#include <vector>
#include <iostream>

template<typename CharT = char, typename TraitsT = std::char_traits<CharT> >
class const_vectorbuf : public std::basic_streambuf<CharT, TraitsT> {
public:
    const_vectorbuf(const std::vector<char>& v) {
        this->setg(v.data(), v.data(), v.data()+v.size());
    }
};

void const_doStuff(const std::vector<char>& v) {
    const_vectorbuf<const char> vbuff(v);
    //std::istream s(&vbuff); With this commented out I get the error below
}

int main(int argc, char** argv) {
    std::vector<char> v = {'a', 'b', 'c'};
    const_doStuff(v);
    return 0;
}

我不知道如何解决它。

错误:

In file included from /usr/include/c++/4.8/ios:40:0,
                 from /usr/include/c++/4.8/ostream:38,
                 from /usr/include/c++/4.8/iostream:39,
                 from vector_stream.cpp:2:
/usr/include/c++/4.8/bits/char_traits.h: In instantiation of ‘static void __gnu_cxx::char_traits<_CharT>::assign(__gnu_cxx::char_traits<_CharT>::char_type&, const char_type&) [with _CharT = const char; __gnu_cxx::char_traits<_CharT>::char_type = const char]’:
/usr/include/c++/4.8/bits/streambuf.tcc:67:63:   required from ‘std::streamsize std::basic_streambuf<_CharT, _Traits>::xsgetn(std::basic_streambuf<_CharT, _Traits>::char_type*, std::streamsize) [with _CharT = const char; _Traits = std::char_traits<const char>; std::streamsize = long int; std::basic_streambuf<_CharT, _Traits>::char_type = const char]’
vector_stream.cpp:36:1:   required from here
/usr/include/c++/4.8/bits/char_traits.h:93:14: error: assignment of read-only reference ‘__c1’
       { __c1 = __c2; }
              ^
In file included from /usr/include/c++/4.8/vector:60:0,
                 from vector_stream.cpp:1:
/usr/include/c++/4.8/bits/stl_algobase.h: In instantiation of ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = const char*; _OI = const char*]’:
/usr/include/c++/4.8/bits/stl_algobase.h:428:38:   required from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = const char*; _OI = const char*]’
/usr/include/c++/4.8/bits/stl_algobase.h:460:17:   required from ‘_OI std::copy(_II, _II, _OI) [with _II = const char*; _OI = const char*]’
/usr/include/c++/4.8/bits/char_traits.h:192:39:   required from ‘static __gnu_cxx::char_traits<_CharT>::char_type* __gnu_cxx::char_traits<_CharT>::copy(__gnu_cxx::char_traits<_CharT>::char_type*, const char_type*, std::size_t) [with _CharT = const char; __gnu_cxx::char_traits<_CharT>::char_type = const char; std::size_t = long unsigned int]’
/usr/include/c++/4.8/bits/streambuf.tcc:56:50:   required from ‘std::streamsize std::basic_streambuf<_CharT, _Traits>::xsgetn(std::basic_streambuf<_CharT, _Traits>::char_type*, std::streamsize) [with _CharT = const char; _Traits = std::char_traits<const char>; std::streamsize = long int; std::basic_streambuf<_CharT, _Traits>::char_type = const char]’
vector_stream.cpp:36:1:   required from here
/usr/include/c++/4.8/bits/stl_algobase.h:390:70: error: no matching function for call to ‘std::__copy_move<false, true, std::random_access_iterator_tag>::__copy_m(const char*&, const char*&, const char*&)’
                        _Category>::__copy_m(__first, __last, __result);
                                                                      ^
/usr/include/c++/4.8/bits/stl_algobase.h:390:70: note: candidate is:
/usr/include/c++/4.8/bits/stl_algobase.h:368:9: note: template<class _Tp> static _Tp* std::__copy_move<_IsMove, true, std::random_access_iterator_tag>::__copy_m(const _Tp*, const _Tp*, _Tp*) [with _Tp = _Tp; bool _IsMove = false]
         __copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result)
         ^
/usr/include/c++/4.8/bits/stl_algobase.h:368:9: note:   template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/stl_algobase.h:390:70: note:   deduced conflicting types for parameter ‘_Tp’ (‘char’ and ‘const char’)
                        _Category>::__copy_m(__first, __last, __result);

因此,尽管 CharT 是 const char streambuf_type 仍然是 char,但我一直在寻找,但到目前为止我还没有找到改变它的方法。 char_traits 中的赋值 __c1 = __c2 我还没来得及开始寻找解决方法。

【问题讨论】:

  • @ildjarn:我不认为它是真的。我的记忆说不是,GCC 同意:coliru.stacked-crooked.com/a/d98e94408a0b7579
  • 不是,第一个例子对我来说是完美的编译。我真正想做的是将向量中的内容放入 google protobuf 消息的字节字段中。
  • @MooingDuck :确实,你是对的;话虽如此,我仍然看不到这段代码的意图,也看不到第一个示例如何正确编译...
  • 创建从向量读取的 istream。 stackoverflow.com/a/8815308
  • 啊,哇,我完全看错了代码。我现在就在路上,抱歉打扰了。

标签: c++11 vector istream


【解决方案1】:

我很确定basic_streambuf 要求它的第一个模板不是-const。另外,我认为basic_streambuf 需要写入权限,因为basic_streambuf 管理输入和输出,无论您最终使用它做什么。您可能还应该覆盖其他一些成员以导致写入失败:sputbackc, sungetc, sputc, sputn, xsputn...

§ 27.2.2/2 在第 27 条的类中,名称为 charT 的模板形参表示包含 char、wchar_t 和 满足对可以实例化任何 iostream 组件的字符的要求

(强调我的)这条规则有点模糊,但我很确定它清楚地涵盖了你的情况。

【讨论】:

  • 啊,这听起来很合理。这可能是我在编程生涯中第一次直接遇到这样的标准。进步!...或其他东西;)
  • 无法通过覆盖xsputn 和公司来消除错误。唯一合理的做法是const_castsetg 指定数据指针(而不是使用const char 作为模板参数)。
  • 根据我了解到的情况,如果您需要 const 强制转换,则设计存在较大问题。
  • @n.m.:我原本想说的是,除了解决问题之外,还应该覆盖这些,因为它们将有助于防止其他问题。
  • @dutt:您对const_cast 的看法是完全正确的,但不幸的是,设计中的错误是basic_streambuf 被用于输入和输出流,而它们本来应该是分开的.大多数人都同意 IOstream 的内部(以及一些外部!)设计不佳,这也是原因之一。
猜你喜欢
  • 1970-01-01
  • 2021-03-21
  • 1970-01-01
  • 2021-11-10
  • 2012-03-07
  • 2010-12-21
  • 1970-01-01
  • 1970-01-01
  • 2021-04-12
相关资源
最近更新 更多