Пакеты параметров и семантика перемещения

Ответ на главный проголосовавший ответ очень хорошо удовлетворяет решению.

В дополнение к этому ответу это может помочь визуализировать то, что происходит немного лучше:

int main()

    int input = 1;//set to 1 for illustrative purposes
    bool cinState = false;
    string test = "\0";
    while(input != -1){//enter -1 to exit
        cout << "Please input (a) character(s): ";//input a character here as a test
        cin >> input; //attempting to input a character to an int variable will cause cin to fail
        cout << "input: " << input << endl;//input has changed from 1 to 0
        cinState = cin;//cin is in bad state, returns false
        cout << "cinState: " << cinState << endl;
        cin.clear();//bad state flag cleared
        cinState = cin;//cin now returns true and will input to a variable
        cout << "cinState: " << cinState << endl;
        cout << "Please enter character(s): ";
        cin >> test;//remaining text in buffer is dumped here. cin will not pause if there is any text left in the buffer.
        cout << "test: " << test << endl;
    }
    return 0;    
}

Сбрасывание текста в буфере переменной не особенно полезен, однако помогает визуализировать, почему cin.ignore() необходим.

Я также отметил изменение входной переменной, потому что, если вы используете переменную ввода в вашем состоянии для цикла while или оператор switch, он может зайти в тупик или выполнить условие, которого вы не ожидали, что может быть более запутанным для отладки.

0
задан Chameleon 15 January 2019 в 21:30
поделиться

2 ответа

Ваша проблема здесь в том, что вы неправильно перенаправляете параметры.

InflateInput<DeflateInput<File>> inflate1(0, File{"filename"}, 9, 0);

Вызывает конструктор

template<typename ...Args>
InflateInput(int header, Args ...args) : source(args...) {}

, где Args... равно File, int, int. Поскольку у args... есть имя, целые пачки являются lvalue, но ваш DeflateInput принимает только rvalue ссылку на File из

DeflateInput(T &&stream, int level, int header) : source(std::move(stream)) {}

. Самый простой способ - вызвать std::move args, как

InflateInput(int header, Args ...args) : source(std::move(args)...) {}

, но на самом деле вы должны использовать пересылку ссылок вместе с std::forward для полной пересылки всех параметров. Это изменит конструктор на

InflateInput(int header, Args&& ...args) : source(std::forward<Args>(args)...) {}
0
ответ дан NathanOliver 15 January 2019 в 21:30
поделиться

Отсутствует идеальная пересылка. Попробуйте ниже

template<typename ...Args>
InflateInput(int header, Args&& ...args) : source(std::forward<Args&&>(args)...) {}

Конструктор ниже принимает ссылку на r-значение типа T. Но InflateInput вызывает с параметром (Args), который является l-значением. Отсюда ошибка компилятора.

DeflateInput(T &&stream, int level, int header) : source(std::move(stream)) {}

Вы можете воспроизвести ту же ошибку, например,

DeflateInput deflate3(file, 5, 0)

https://gcc.godbolt.org/z/Oe2q68

0
ответ дан balki 15 January 2019 в 21:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: