Ассоциативность фолд-выражений
N4191 предложил сложение выражений в C++. Определение там было
(args + ...)
это левый сгиб (т.е. (((a0 + a1) + a2) + ...)
и что
(... + args)
вправо (т.е. (... + (a8 + (a9 + a10)))
, Однако пересмотренный документ N4295 отменил определения левого и правого одинарного сгиба.
Вопрос: в чем обоснование? Это кажется более интуитивным (по крайней мере, когда вы привыкли к алфавиту слева направо), чтобы оценить (args + ...)
слева направо.
2 ответа
Из комментария @cpplearner, вот некоторая археология из std-Discussion
В среду, 4 февраля 2015 года, в 1:30 утра @TC написал:
В N4295, который фактически был утвержден в качестве стандарта,
(... op e)
является одинарной левой складкой;
(e op ...)
одинарная правая складка;В N4191, однако,
(e op ...)
называется левой складкой
(... op e)
называется правой складкойПочему поворот на 180 градусов?
И ответ @RichardSmith
Форма в оригинальной статье была просто опечаткой. Вот несколько причин, почему определение, за которое проголосовали в стандарте, является правильным:
В формулировке стандарта
(e op ...)
имеет подвыражения вида(e_i op <stuff>)
, У него нет подвыражений вида(<stuff> op e_i)
, Это согласуется со всеми другими расширениями пакета, где расширение содержит повторяющиеся экземпляры шаблона.
(e op ... op eN)
, гдеeN
не является пакетом, должен иметьeN
как самый внутренний операнд, чтобы быть полезным - то есть он должен быть(e1 op (e2 op (e3 op (... op eN)...)))
не(...(((e1 op e2) op e3) op ...) op eN)
- и наоборот для(e0 op ... op e)
, Это позволяет, например,(string() + ... + things)
а также(std::cout << ... << things)
работать. Для согласованности(e op ...)
также должен быть(e1 op (e2 op (...)))
,
Я не могу говорить за предложение, но новые, измененные определения кажутся мне естественными. Мое обоснование для этого заключается в том, что (... + args)
является суб-выражением левой складки, и (args + ...)
является суб-выражением правой складки. На самом деле, первый - это последний сегмент, а второй - начальный сегмент выражения (возможно, я не использую правильную терминологию).
Вот как я бы проиллюстрировал расширение сгиба от синтаксиса:
Левый сгиб
(... + args)
(... + args) + a999)
(... + args) + a998) + a999)
((...((a0 + a1) + a2)...) + a999)
Правый сгиб
(args + ...)
(a0 + (args + ...)
(a0 + (a1 + (args + ...)
(a0 + (...(a997 + (a998 + a999))...))