goldvitaly's blog

By goldvitaly, 11 years ago, In Russian

Всем привет! Думаю, что многие слышали, что в 2011 году вышел новый стандарт языка программирования c++. Возможности языка с новым стандартом существенно расширены, благодаря чему стало возможно делать довольно удобные вещи. Когда появляется что-то новое, то сразу хочется это попробовать на чем-нибудь полезным.

Проект testlib.hpp содержит реализацию библиотеки для разработки чекеров и генератов для олимпиадных задач. Идея разработать такую библиотеку совсем не новая, развитие множества таких библиотек происходит уже больше десяти лет. Такие библиотеки есть для огромного количества языков программирования. В России все начиналось с паскаля, потом появились библиотеки и для c++, python, java.

Зачем нужна еще одна библиотека? Затеяв разработку этой библиотеки, я преследовал множество целей.

  1. Первая цель была учебная. Эту библиотеку полностью разработали два человека: riadwaw и map. Мне кажется, что эта цель удалась. Ребятам потребовалось узнать много нового не только в языке c++ и его новом стандарте, но и в целом был получен полезный опыт общих принципов программирования.
  2. Второй целью была расширяемость. Под расширяемостью здесь я подразумеваю возможность добавлять функциональность без изменения кода библиотеки. Это принцип, который используется при создании всех общих библиотек и фраймворков.
  3. Реализация современных интерфейсов, принятых в языке c++. Поддержка совместимости с stl, поддержка stream интефейсов << и >>.

Если первая цель удалась, то что же получилось со второй и третьей я расскажу описанием самой библиотеки.

Начнем с простого примера:

#include "testlib.hpp"
TESTLIB_CHECK(){
    verifyEqual(ouf.read<int>(), ans.read<int>());
    OK("1 number");
}

Отличия от testlib.h на этом примере не столь существенны. Однако видно, что чтение реализовано шаблонной функцией. Возможно это не привычно, но позволяет расширять библиотеку.

Посмотрим еще один пример, в котором происходит считывание вектора. Приведено лишь два варианта, существуют и другие с указанием разделителей.

#include "testlib.hpp"
#include <vector>

using namespace std;
TESTLIB_CHECK(){
        //Считывает вектор из n чисел, разделенных пробелом
	vector<long long> v1 = ouf.read<vector<long long>>(n);
        //Считывает вектор из n чисел, с ограничениями на каждое число от 1 до 100
	vector<long long> v2 = ouf.read<vector<long long>>(n,
                make_default_reader<long long>(1, 100));
}

На текущий момент поддерживается чтение целых чисел, чисел с плавающей точкой, pair, vector, string.

Метод read<string> по умолчанию читает token, однако любой объект можно считать альтернативным способом. Для этого нужно первым аргументом передать Reader.

Если нужно часто считывать какой-то объект с недефолтным reader, то можно воспользоваться классом Alias:

typedef Alias<string, LineReader> Line;
//теперь
string nextLine = inf.read<Line>();
//эквивалентно записи
string nextLine = inf.read<string>(LineReader());
//или
LineReader reader;
string nextLine = inf.read<string>(reader);

Библиотеку можно расширять двумя способами

  1. добавление новой функциональности в библиотеку. Это всегда не так просто, так как библиотека довольно сложная и не многие захотят в ней разбираться. Хотя развитие этой библиотеки на мой субъективный взгляд довольно интересно и познавательно.
  2. добавление новых пользовательских классов, которые автоматические станут поддерживаться библиотекой без ее изменения. (немного об этом есть в tutorial). Этот способ крайне прост и практически не требует понимания внутреннего устройства библиотеки. Это может быть оформлено как отдельный файл, который может распространяться отдельно, либо быть включен в библиотеку. Разве не хочется в чекере писать просто inf.read<Point> и получать сразу точку на плоскости?

Текущую версию в одном файле можно скачать отсюда. Данный файл автосгенерирован, поэтому, если вы хотите посмотреть на устройство проекта или хотите решить не поучавствовать ли в разработке, то лучше смотреть репозиторий. Там же вы найдете чуть более подробную документацию.

  • Vote: I like it
  • +51
  • Vote: I do not like it