Ответ на главный проголосовавший ответ очень хорошо удовлетворяет решению.
В дополнение к этому ответу это может помочь визуализировать то, что происходит немного лучше:
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, он может зайти в тупик или выполнить условие, которого вы не ожидали, что может быть более запутанным для отладки.
Ваша проблема здесь в том, что вы неправильно перенаправляете параметры.
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)...) {}
Отсутствует идеальная пересылка. Попробуйте ниже
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)