Подтвердить что ты не робот

Функция выражения слэба функции С++ lambda

на самом деле я не знаю, как быть очень точным.

Сегодня я просмотрел следующую страницу:

http://siliconframework.org/docs/hello_world.html

Я нашел следующий синтаксис:

GET / _hello = [] () { return D(_message = "Hello world."); }

Я обнаружил, что "GET" может быть функцией по выражению лямбда, но я не могу понять, что здесь означают "/" и "_hello", и как они соединяются с чем-то значимым.

Кроме того, что такое "_message ="?

Кстати, мои основные знания на С++ до С++ 11.

Я немного поработал в googled.

Может ли кто-нибудь любезно дать объяснение?

4b9b3361

Ответ 1

В этой библиотеке используется так называемый встроенный доменный специфический язык, где он искажает синтаксис С++ и препроцессора способами, которые позволяют кажущемуся другому языку быть просто еще одной частью программы на С++.

Короче говоря, магия.

Первый бит магии заключается в следующем:

iod_define_symbol(hello)

который является макросом, который генерирует идентификатор _hello типа _hello_t.

Он также создает тип _hello_t, который наследует от CRTP-помощника, который называется iod::symbol<_hello_t>.

_hello_t переопределяет различные операторы (включая operator= и operator/) способами, которые не делают то, что вы обычно ожидаете от поведения объектов С++.

GET / _hello = [] () { return D(_message = "Hello world."); }

поэтому он вызывает

operator=(
  operator/( GET, _hello ),
  /* lambda_goes_here */
);

аналогично в лямбда:

D(_message = "Hello world.");

является

D( operator=(_message, "Hello world.") );

operator/ и operator= могут делать почти что угодно.

В случае D = не выполняет никаких присваиваний - вместо этого он строит структуру, которая в основном говорит, что для поля, называемого "message", присваивается значение "Hello world.".

_message знает, что он называется "message", потому что он был сгенерирован макросом iod_define_symbol(message), где они взяли строку message и сохранили ее с типом _message_t, и создали переменную _message, которая экземпляр этого типа.

D принимает несколько таких пар ключ/значение и связывает их вместе.

Лямбда возвращает этот пакет.

Итак, [] () { return D(_message = "Hello world."); } - это лямбда, которая возвращает пучок вложений в пару ключей, написанных странным образом.

Затем мы вызываем operator= с GET/_hello в левой части.

GET - это еще один глобальный объект с operator/, перегруженным на нем. Я не отслеживал это. Предположим, что это тип iod::get_t (я составил это имя: опять же, я не искал, какой тип он есть, и это не имеет большого значения)

Затем iod::get_t::operator/(iod::symbol<T> const&) перегружается для создания еще одного вспомогательного типа. Этот тип получает имя T (в данном случае "hello") и ожидает, что ему будет присвоен лямбда.

При назначении, он не выполняет то, что вы ожидаете. Вместо этого он отключается и создает связь между "hello" и вызовом этой лямбда, где ожидается, что лямбда вернет набор пар ключ-значение, сгенерированных с помощью D.

Затем мы передаем одну или несколько таких ассоциаций в http_api, которая собирает эти пакеты и строит данные, необходимые для запуска веб-сервера с этими запросами и этими ответами, возможно, включая флаги: "Я собираюсь быть http сервер".

sl::mhd_json_serve затем берет эти данные, номер порта и фактически запускает веб-сервер.

Все это - куча слоев абстракции, чтобы сделать некоторое отражение легче. Созданные структуры имеют И ++ идентификаторы и аналогичные строки. Аналогичные строки отображаются в них, и когда генерируется код сериализации json (или десериализации), эти строки используются для чтения/записи значений json.

Макросы просто существуют, чтобы облегчить запись шаблона.

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

Некоторые из вышеперечисленных содержат незначительную "ложь, рассказанную детям" - в частности, синтаксис оператора не работает так, как я подразумевал. (a/b не эквивалентен operator/(a,b), поскольку второй не будет вызывать оператор-член /. Понимая, что это просто функции, я намерен, а не то, что синтаксис один и тот же.)

@mattheiuG (автор этой структуры) поделился этими слайдами в комментарии ниже этого сообщения, которое далее объясняет D, а _message токены и рамки.

Ответ 2

Это не стандартный синтаксис С++, вместо этого он определен как фреймворк. Элементы с префиксом подчеркивания (_hello, _message и т.д.) Используются с генератором определения символов, который запускает и создает необходимые определения перед компиляцией.

Там есть еще информация об этом в конце этой страницы: http://siliconframework.org/docs/symbols.html. Qt делает аналогичную вещь с ее инструментом moc.