Skip to content

Reader с зафиксированными аргументами

goldvitaly edited this page Dec 29, 2012 · 16 revisions

Предположим, что мы столкнулись с задачей считать vector<int> из n int-ов, каждый из которых от l до r. Заметим, что [DefaultReader<vector<int>>](Default Readers Documentation#wiki-vector) принимает экземпляр класса Reader<int>. А у [DefaultReader<int>](Default Readers Documentation#wiki-int) есть нужный нам метод чтения чисел из отрезка. Но мы не можем "сказать", чтобы DefaultReader<int> при передаче в DefaultReader<vector<int>> вызывал у себя метод read(l, r), а не метод read(), который по умолчанию вызывается в DefaultReader<vector<int>>. Для этого есть функция, которая будет, во-первых, принимать reader (типа T) и аргументы, которые мы хотим передавать при каждом вызове метода read() (в рассматриваемом примере это l и r), и, во-вторых, выдавать нужный нам superReader (также типа T), так что reader.read(Args) == superReader.read().
Таких функций даже две:

  • make_reader (T reader, Args... args) - возвращает Reader, который при вызове метода read будет вызывать reader.read(args...).
    Использование (реализация чтения в ситуации, описанной в начале): auto reader = make_reader(DefaultReader<int>(), l, r); - считает число (если оно не принадлежит отрезку [l; r], то выдает WA).
  • make_default_reader (Args args) - возвращает DefaultReader<T>, который при вызове метода read будет вызывать DefaultReader().read(args...).

Реализованы данные обертки в данный момент в виде класса ReaderWrapper, но не стоит считать, что так будет всегда.

Использование:
auto reader = make_default_reader<int>(l, r) - считает число от l до r.

Внимание! Пример неправильного использования: (TODO: добиться, чтобы такое не компилировалось) Reader<int> reader = make_default_reader<int>(l, r) - неверно, так как make_default_reader<int>(l, r) создаст наследника класса Reader<int> и наше присваивание "уничтожит его индивидуальность", то есть оставит пустую внутренность, соответствующую классу Reader. Поэтому вы можете добиться того, что вам нужно, либо используя auto, либо указав полное имя класса, что делать не рекомендуется, ибо инвариантность возвращаемого типа не гарантируется в последующих версиях библиотеки.