Дразнить поток для тестирования - PullRequest
0 голосов
/ 19 ноября 2018

Исходя из Получить istream из символа *, я пытаюсь написать контейнер фиктивного потока для некоторых тестов, который выглядит следующим образом:

struct mock_membuf : std::streambuf
{
    mock_membuf(char* begin, char* end) {
        this->setg(begin, begin, end);
    }
};

struct MockStreamContainer{
    explicit MockStreamContainer(char* buffer, int offset, int nbytes): m_sbuf(buffer + offset, buffer + offset + nbytes), m_body(&m_sbuf), m_size(nbytes) {}

    std::istream& Body() const {
        return m_body;
    }

    int Size() const {
        return m_size;
    }

    mock_membuf m_sbuf; // same as membuf from the question referenced
    std::istream& m_body;
    int64_t m_size;
};

и будет использоватьсяследующим образом:

int main()
{
    char buffer[] = "I'm a buffer with embedded nulls\0and line\n feeds";

    auto get_stream = [&buffer](int offset, int nbytes) {
        return MockStreamContainer(buffer, offset, nbytes);
    };
    std::string line;
    auto r = get_stream(5, 10);
    std::istream& in = r.Body();
    while (std::getline(in, line)) {
        std::cout << "line: " << line << "\n";
    }
    return 0;
}

Приведенный выше код является просто тем, что я пробовал (здесь ссылка ), и содержит ошибки - Есть предложения относительно того, как это можно правильно и эффективно реализовать?

PS В соответствии с запросом приведенный выше код в настоящее время вызывает следующую ошибку компиляции:

main.cpp: In constructor 'MockStreamContainer::MockStreamContainer(char*, int, int)':

main.cpp:17:131: error: invalid initialization of non-const reference of type 'std::istream&' {aka 'std::basic_istream<char>&'} from an rvalue of type 'mock_membuf*'

     explicit MockStreamContainer(char* buffer, int offset, int nbytes): m_sbuf(buffer + offset, buffer + offset + nbytes), m_body(&m_sbuf), m_size(nbytes) {}

Редактировать: Благодаря ответу @Martin York я смог решить проблемувнеся незначительное изменение: преобразуйте m_body в указатель вместо ссылки.

1 Ответ

0 голосов
/ 19 ноября 2018

Ваша переменная-член m_body является ссылкой:

std::istream&    m_body;
            ^     reference

Итак, вы пытаетесь инициализировать эту ссылку путем создания временного в конструкторе.

explicit MockStreamContainer(char* buffer, int offset, int nbytes):
    m_sbuf(buffer + offset, buffer + offset + nbytes),
    m_body(&m_sbuf),    // Here you are passing a pointer to `std::streambuf`
                        // This is not an `std::istream` so the compiler
                        // is trying to create one using the single argument
                        // constructor.
                        //
                        // That worked. So you have a temporary `std::istream` object
                        //
                        // You can not bind a temporary object to a non const reference
                        // hence the compiler error.
    m_size(nbytes)
{}

Я бы сделал это:

#include <iostream>

struct mock_membuf : public std::streambuf
{
    mock_membuf(char* begin, char* end) {
        this->setg(begin, begin, end);
    }
};

struct mock_stream: public std::istream
{
    mock_membuf     streamBuffer;
    public:
        mock_stream(char* buffer, int offset, int nbytes)
            : std::istream(nullptr)
            , streamBuffer(buffer + offset, buffer + offset + nbytes)
        {
            rdbuf(&streamBuffer);
        }
};

int main()
{
    char buffer[] = "I'm a buffer with embedded nulls\0and line\n feeds";

    std::string line;
    mock_stream in(buffer, 5, 10);
    while (std::getline(in, line)) {
        std::cout << "line: " << line << "\n";
    }
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...