nixp.ru v3.0

20 января 2017,
пятница,
17:12:11 MSK

Аутсорсинг Linux с компанией «Флант»
newcomer написал 13 мая 2008 года в 15:24 (751 просмотр) Ведет себя неопределенно; открыл 3 темы в форуме, оставил 17 комментариев на сайте.

Привет!

Решил написать код, который бы смотрел как меняются указатели на буфер при чтении и записи в различных потоковых классах, в часности в filebuf (basic_filebuf):

#include
#include
#include
using namespace std;
class inspectorfile:public fstream{
      public:
            inspectorfile(const char*file):fstream(file){}
            void print(){
            cout<<"put buffer: ";
            cout<<(const void*)(rdbuf()->pbase())<<' '<<(const void*)(rdbuf()->pptr())<<' '<<(const void*)(rdbuf()->epptr())<<" : "<<*((const char*)(rdbuf()->pptr()))<<endl;
            cout<<"get buffer: ";
            cout<<(const void*)(rdbuf()->eback())<<' '<<(const void*)(rdbuf()->gptr())<<' '<<(const void*)(rdbuf()->egptr())<<endl;
            cout<<endl;
            }
};
int main(){
      int i=0;
      char c='?';
      inspectorfile fs("file");
      fs.print();
      fs<<"hello";
      fs.print();
      fs.seekg(1);cout<<"seek"<<endl;
      fs.print();
      fs>>c;
      cout<<"read character: "<<c<<endl;
      fs.print();
      return 0;
}

Объявляю класс от fstream’а.

В нём метод rdbuf() возвращает указатель на буфер, который использует fstream.

Далее, существуют методы, которые возвращают указатели на начало, конец и текущую позицию read/write буфера и того их шесть:

pbase

pptr

epptr

eback

gptr

egptr

Но проблема в том, что эти методы protected. Для того что бы их вызвать я решил сделать inspectorfile дружественный для filebuf.

В OpenBSD (gcc 3.3.5) всё проходит успешно.

В Linux Slackware 12 (gcc 4.1.2) выводятся ошибки:

/usr/lib/gcc/i486-slackware-linux/4.1.2/../../../../include/c++/4.1.2/streambuf: In member function 'void inspectorfile::print()':
/usr/lib/gcc/i486-slackware-linux/4.1.2/../../../../include/c++/4.1.2/streambuf:516: error: '_CharT* std::basic_streambuf<_CharT, _Traits>::pbase() const [with _CharT = char, _Traits = std::char_traits]' is protected
filestream.cc:29: error: within this context
/usr/lib/gcc/i486-slackware-linux/4.1.2/../../../../include/c++/4.1.2/streambuf:519: error: '_CharT* std::basic_streambuf<_CharT, _Traits>::pptr() const [with _CharT = char, _Traits = std::char_traits]' is protected
filestream.cc:29: error: within this context
/usr/lib/gcc/i486-slackware-linux/4.1.2/../../../../include/c++/4.1.2/streambuf:522: error: '_CharT* std::basic_streambuf<_CharT, _Traits>::epptr() const [with _CharT = char, _Traits = std::char_traits]' is protected
filestream.cc:29: error: within this context
/usr/lib/gcc/i486-slackware-linux/4.1.2/../../../../include/c++/4.1.2/streambuf:519: error: '_CharT* std::basic_streambuf<_CharT, _Traits>::pptr() const [with _CharT = char, _Traits = std::char_traits]' is protected
filestream.cc:29: error: within this context
/usr/lib/gcc/i486-slackware-linux/4.1.2/../../../../include/c++/4.1.2/streambuf:469: error: '_CharT* std::basic_streambuf<_CharT, _Traits>::eback() const [with _CharT = char, _Traits = std::char_traits]' is protected
filestream.cc:31: error: within this context
/usr/lib/gcc/i486-slackware-linux/4.1.2/../../../../include/c++/4.1.2/streambuf:472: error: '_CharT* std::basic_streambuf<_CharT, _Traits>::gptr() const [with _CharT = char, _Traits = std::char_traits]' is protected
filestream.cc:31: error: within this context
/usr/lib/gcc/i486-slackware-linux/4.1.2/../../../../include/c++/4.1.2/streambuf:475: error: '_CharT* std::basic_streambuf<_CharT, _Traits>::egptr() const [with _CharT = char, _Traits = std::char_traits]' is protected
filestream.cc:31: error: within this context
filestream.cc: In function 'int main()':
filestream.cc:39: error: reference to 'inspectorfile' is ambiguous
filestream.cc:23: error: candidates are: class inspectorfile
/usr/lib/gcc/i486-slackware-linux/4.1.2/../../../../include/c++/4.1.2/streambuf:123: error:                 struct std::inspectorfile
filestream.cc:39: error: reference to 'inspectorfile' is ambiguous
filestream.cc:23: error: candidates are: class inspectorfile
/usr/lib/gcc/i486-slackware-linux/4.1.2/../../../../include/c++/4.1.2/streambuf:123: error:                 struct std::inspectorfile
filestream.cc:39: error: expected `;' before 'fs'
filestream.cc:41: error: 'fs' was not declared in this scope

friend class inspectorfile; объявил в классе basic_filebuf

ругается компилятор почему-то на basic_streambuf, на всякий случай я объявил и там, но ошибка не исчезла.

Подскажите, пожалуйста, в чём проблема.

rgo

Компилятор ругается не случайно. Если basic_streambuf имеет protected-члены, то компилятор гарантирует, что никто кроме потомков и друзей их не будет использовать. Для того, чтобы стать другом basic_filebuf, надо влезть в сорцы libstdc++ и сделать из неё libNONstdc++.

Если очень хочется именно так, я бы попытался сделать такое:

class my_filebuf : public basic_filebuf >
{
      friend class inspectorfile;
};
/*...*/
class inspectorfile: // ...
    void print () {
        const my_filebuf *buf =
                  static_cast (rdbuf ());
        /* ... */
        cout << buf->pbase ();
        /* ... */

С точки зрения ООП — это гадость: мы насильно повышаем тип от basic_filebuf до my_filebuf, причём не по теме повышаем. Но доступ у нас, появляется.

newcomer
rgo
Компилятор ругается не случайно. Если basic_streambuf имеет protected-члены, то компилятор гарантирует, что никто кроме потомков и друзей их не будет использовать. Для того, чтобы стать другом basic_filebuf, надо влезть в сорцы libstdc++ и сделать из неё libNONstdc++.

Зачем лезть в сырцы, когда доступ задаётся в заголовках?

Хорошо, я залез в сырцы, и что мне там менять?

rgo

Я думаю, стоит изменить заголовки и пересобрать libstdc++. Стоит заглянуть в сырцы, и подогнать их под заголовки. Не знаю. Я с c++ сталкиваюсь лишь эпизодически, при этом изо всех сил стараясь этих столкновений избегать.

newcomer
rgo
Я думаю, стоит изменить заголовки и пересобрать libstdc++. Стоит заглянуть в сырцы, и подогнать их под заголовки.

Я думаю вряд ли потому как спецификации доступа для этапа компиляции существуют. На код они не влияют, наверно… Во всяком случае на новый класс, на новый код.

Какие нибудь идеи есть?

metal

Скомпилироваться должно, если в заголовках правильно поправил. Точно не хватает ; после конструктора. Как-то править заголовки libstdc++ у меня нет желания.

newcomer
rgo
Я думаю, стоит изменить заголовки и пересобрать libstdc++.

Всяко это не так, так как за проверку синтаксиса отвечает компилятор, а не линковщик. И ему нет дела какой есть бинарный код…

ecobeingecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.