Представьте, что вы пишете какой-нибудь программный инструмент на C++. Не очень сложный инструмент и не такой, в котором вас бы заботила производительность настолько, что вы бы стали использовать более быстрые структуры данных вместо тех, которые предоставляет стандартная библиотека, а такой инструмент, для работы с которым, как вам кажется, было бы не лишним добавить пару параметров. После не очень дотошного и не очень вдохновляющего ресерча этого вопроса вы остановились на старом добром стандарте реализации программных параметров – вы собираетесь парсить argv. Парсинг параметров командной строки попадает в кошмарную зону сложности. Это не настолько тривиально, что существует один очевидный подход, и не настолько сложно, чтобы быть исключительно областью научных статей, публикуемых экспертами в предметной области. Скорее, это доступная проблема, которую каждый хочет попробовать решить, а затем поскорее написать пост в блоге о своем умном маленьком решении, из-за чего результаты поиска просто затоплены бесконечным посредственным кодом. И это достаточно распространенная проблема. Мой младший брат недавно пытался найти решения для задачи разбиения множества чисел, лучшие алгоритмы для которой хорошо известны в академических кругах. К своему ужасу, он напоролся на множество постов на StackOverflow, описывающих совершенно недееспособные решения, которые даже не реализуют известные алгоритмы. С учетом вышеизложенного, вот мое умное маленькое решение. Требования к моему обработчику argv будут следующими: Достаточно декларативный Генерирует POD-структуру Никаких внешних зависимостей Простое добавление и удаление настроек Так как я хочу, чтобы на выходе получалась POD-структура, это послужит отличной отправной точкой: Листинг 1 Несколько замечаний по коду в Листинге 1: help и verbose являются логическими значениями, которые можно устанавливать с помощью простых флагов. outfile требует параметр и не может быть установлен простым флагом. infile не предполагает никаких флагов, устанавливается, когда параметр не является распознанным флагом. value не является ни строкой, ни логическим значением, поэтому необходимо будет выполнять какое-то преобразование. Мой излюбленный способ ветвления на основе строк — использовать map над std::function: Листинг 2 В Листинге 2 мы видим неупорядоченную map, при поиске по строке в которой будет выдаваться лямбда (или другой std::function-прибамбас), которая сможет выполнить соответствующую модификацию MySettings. Если это показалось вам чрезвычайно очевидным и простым, то это потому, что это так и есть. С точки зрения стиля здесь может быть уместно использование макроса с целью свести к минимуму повторение и сделать код более декларативным: Листинг 3 Конечно, существуют религиозные течения, которые учат, что препроцессор C — от лукавого. Но лично для меня моя бессмертная душа значит все меньше и меньше, поэтому макросом я не побрезгую. Для параметров с одним аргументом мы просто повторяем этот подход. Наши лямбда-выражения теперь будут принимать два аргумента, первый из которых структура MySettings, а второй — строка: Листинг 4 С этого момента должно быть очевидно, что этот подход можно масштабировать на поддержку флагов с произвольным количеством аргументов и сложностью парсинга. Все, что нам осталось сделать, это собрать все кусочки воедино и наконец-таки распарсить argv. Нам понадобится функция, которая делает четыре вещи в следующем порядке: Проверяет, является ли строка из argv NoArgs-опцией, и если это так, вызывает соответствующий обработчик Проверяет, является ли строка OneArg-опцией, и, если это так, извлекает строковый аргумент (пробрасывая исключения, если такого аргумента не существует), затем вызывает соответствующий обработчик. Проверяет, был установлен infile, и если нет, то устанавливает в него строку. Предупреждает, если infile уже установлен и флаг не распознан Давай напишем ее: Листинг 5 Это минус целых 50 dkp, если вы не справитесь с этим! Парсинг argv не является сложной проблемой, и я не претендую на то, что представленное здесь решение является инновационным или новаторским. Тем не менее, если верить интернету, для обработки этих скромных флагов требуется как минимум один платформоспецифичный фреймворк или один заголовочный файл, скопированный у доктора Доббса (Dr. Dobb) где-то в 2003 году. Зависимости — это не обязательно плохо, но C++ — это не Javascript. Нет необходимости задействовать сторонние фреймворки для решения проблемы, с которой мы можем разобраться сами в несколько десятков строк кода. Завтра вечером пройдет открытое занятие на тему «Объектно-ориентированное программирование средствами C++».  Что будет на занятии: инкапсуляция, наследование и полиморфизма глазами C++ программиста; преимущества и недостатки активного использования полиморфизма в программах. Чему научитесь: объявлять классы и разграничивать области видимости методов и полей, создавать иерархии наследования, реализовывать полиморфное поведение. Регистрация на бесплатный урок  Редактор