<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Форум 'C/C++' на RSDN</title>
    <link>http://rsdn.org/Forum/cpp/</link>
    <description>Программирование на C++. No VCL, no MFC, pure C++ only.</description>
    <category>cpp</category>
    <language>ru-ru</language>
    <copyright>Copyright ©, RSDN, 2001-2007</copyright>
    <webMaster>forum@rsdn.org</webMaster>
    <generator>RSDN RSS Generator 1.3</generator>
    <image>
      <url>http://rsdn.org/rsdn.gif</url>
      <title>RSDN</title>
      <link>http://rsdn.org</link>
    </image>
    <lastBuildDate>Sun, 21 Jun 2026 13:11:35 GMT</lastBuildDate>
    <ttl>5</ttl>
	<item>
		<title>Вопрос по непонятому из С++20 короутин</title>
		<link>http://rsdn.org/Forum/cpp/9101840.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9101840</guid>
		<comments>http://rsdn.org/Forum/cpp/9101840</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9101840</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9101840</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9101840</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;Доброго дня!&lt;br /&gt;
&lt;br /&gt;
В очередной раз пытаюсь разобраться с короутинами из C++20. Среди того, что не понимаю, есть один момент, который можно обозначить как "идеология обращения с асинхронными сущностями". Попробую пояснить о чем речь.&lt;br /&gt;
&lt;br /&gt;
Большинство примеров использования короутин демонстрируют co_await в одну операцию. Что-то вроде:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;&lt;span class='kw'&gt;auto&lt;/span&gt; socket = co_await socket_factory::connect(ip);
co_await socket.send(request_packet);
&lt;span class='kw'&gt;auto&lt;/span&gt; reply = co_await socket.receive();
...&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Но, насколько я смог понять, в реальности за &lt;tt&gt;co_await something()&lt;/tt&gt; стоит два шага:&lt;br /&gt;
&lt;br /&gt;
1. Вызов something() и получение некого Task-а как результат формирования короутины something (под Task-ом понимается тип возвращаемого something() значения, это может быть и не Task, а какой-нибудь generator или еще что-то, что хранит в себе coroutine_handle из something()).&lt;br /&gt;
2. Применение оператора co_await к возвращенному из something() Task-у. С последующей цепочкой вызовов await_ready/await_suspend/await_resume для Awaiter-а (или самого Task-а, если отдельного Awaiter-а нет).&lt;br /&gt;
&lt;br /&gt;
Поэтому, при желании, программист может переписать строчку &lt;tt&gt;co_await socket_factory::connect(ip);&lt;/tt&gt; в более развернутом виде:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;&lt;span class='com'&gt;// Получили в свое распоряжение короутину connect.&lt;/span&gt;
&lt;span class='kw'&gt;auto&lt;/span&gt; connect_task = socket_factory::connect(ip);
... &lt;span class='com'&gt;// Тут курим бамбук.
// И только сейчас толкаем ее на выполнение.&lt;/span&gt;
&lt;span class='kw'&gt;auto&lt;/span&gt; socket = co_await connect_task;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Теперь к сути вопроса.&lt;br /&gt;
&lt;br /&gt;
Допустим, у меня есть очередь сообщений и я хочу сделать к ней async_receive, который бы представлял из себя короутину. Т.е. что-то вроде:&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;async_receive_task_t async_receive(message_queue_t queue) {
  ... &lt;span class='com'&gt;// Какие-то действия с co_yield/co_return.&lt;/span&gt;
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
И чтобы к этому async_receive можно было применять co_await:&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;&lt;span class='kw'&gt;auto&lt;/span&gt; msg = co_await async_receive(commands_queue);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Сейчас у меня есть мысль, что в async_receive сразу при входе можно делать попытку чтения из очереди. И если очередь не пуста, то немедленно доставать сообщение оттуда.&lt;br /&gt;
&lt;br /&gt;
Т.е. мой async_receive_task_t::promise_type::initial_suspend будет возвращать std::suspend_never, а async_receive будет работать как-то так:&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;async_receive_task_t async_receive(message_queue_t queue) {
  &lt;span class='com'&gt;// Сразу пытаемся взять сообщение если очередь не пуста.&lt;/span&gt;
  &lt;span class='kw'&gt;auto&lt;/span&gt; msg = queue.try_get_nonblocking();

  &lt;span class='com'&gt;// Если взять не удалось, то будем ждать возвращения в эту короутину
  // из нашего async_receive_task_t::awaiter_t::await_suspend.&lt;/span&gt;
  &lt;span class='kw'&gt;if&lt;/span&gt;(!msg) {
    co_yield empty_queue;
    &lt;span class='com'&gt;// А когда нам вернут управление, то сделаем еще одну попытку.&lt;/span&gt;
    msg = ...;
  }

  co_return msg;
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Такой "энергичный" подход вроде как хорош тем, что не нужно тратить время если очередь сообщений не пуста. Сразу же внутри async_receive получаем сообщение, наш awaiter_t об этом узнает и вернет true из await_ready. Соответственно, не придется делать попытку приостановить ту короутину, в которой обратились к async_receive.&lt;br /&gt;
&lt;br /&gt;
Однако, меня смущает потенциальная возможность вот какого сценария:&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;&lt;span class='kw'&gt;auto&lt;/span&gt; receive_coro = async_receive(command_queue); &lt;span class='com'&gt;// (1)
// Теперь у нас на руках есть короутина async_receive, но в приостановленном
// состоянии.&lt;/span&gt;
...
... &lt;span class='com'&gt;// Еще какие-то действия.&lt;/span&gt;
...
&lt;span class='kw'&gt;if&lt;/span&gt;(something_went_wrong) &lt;span class='kw'&gt;return&lt;/span&gt;; &lt;span class='com'&gt;// Дальше не идем.

// Только сейчас нам нужно сообщение из очереди.&lt;/span&gt;
&lt;span class='kw'&gt;auto&lt;/span&gt; msg = co_await receive_coro; &lt;span class='com'&gt;// (2)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
При "энергичном" подходе если в command_queue было сообщение, то это сообщение будет извлечено в точке (1). Однако, если дело до точки (2) не дойдет, то сообщение будет потеряно. &lt;br /&gt;
&lt;br /&gt;
Что мне кажется неправильным. Ведь co_await-а не было. А значит и явной попытки взять сообщение в обработку не было.&lt;br /&gt;
&lt;br /&gt;
Возможно, правильным был бы "ленивый" подход, в котором promise_type::initial_suspend возвращал бы std::suspend_always. Сама короутина async_receive создавалась бы в приостановленном состоянии, а первая попытка чтения из очереди была бы в awaiter_t::await_suspend. И чтобы awaiter_t::await_suspend возвращал true только если очередь пуста и нужно приостанавливаться до появления в ней сообщений (соответственно, если в awaiter_t::await_suspend сообщение удалось взять, то возвращается false).&lt;br /&gt;
&lt;br /&gt;
Собственно, сам вопрос: правильно ли я понимаю, что с точки зрения C++ных короутин более уместно использовать именно "ленивый" подход для такой гипотетической async_receive?&lt;br /&gt;
&lt;br /&gt;
PS. Про рекомендацию возвращать из promise_type::initial_suspend значение std::suspend_always читал неоднократно. Здесь больше вопрос в том, насколько это уместно с точки зрения нужного мне async_receive.&lt;br /&gt;
&lt;br /&gt;
PPS. Про &lt;a class="m" href="https://lewissbaker.github.io/2020/05/11/understanding_symmetric_transfer" target="_blank"&gt;symmetric transfer&lt;/a&gt; тоже читал. Но есть ощущение, что для моего async_receive достаточно будет возврата bool-а из awaiter_t::await_suspend.&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Thu, 18 Jun 2026 13:21:56 GMT</pubDate>
		
			<author>so5team &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>37</slash:comments>
		
	</item>

	<item>
		<title>Про умные указатели пр. безопасные фишки</title>
		<link>http://rsdn.org/Forum/cpp/9097513.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9097513</guid>
		<comments>http://rsdn.org/Forum/cpp/9097513</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9097513</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9097513</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9097513</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;Вопрос такой, особенно к @sergey2b и прочим, кто привык к старому C++.&lt;br /&gt;
&lt;br /&gt;
Используете ли вы везде умные указатели или же вам удобнее по старинке и т.н. умные указатели только мешают?&lt;br /&gt;
&lt;br /&gt;
Аналогичный вопрос &amp;mdash; про потоки. Используете ли либы с корутинами (какие?) или же по старинке с ручной синхронизацией?&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Sat, 06 Jun 2026 16:35:29 GMT</pubDate>
		
			<author>Shmj &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>76</slash:comments>
		
	</item>

	<item>
		<title>equality_comparable_with</title>
		<link>http://rsdn.org/Forum/cpp/9096782.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9096782</guid>
		<comments>http://rsdn.org/Forum/cpp/9096782</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9096782</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9096782</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9096782</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;Понадобилось мне завести семейство классов, с одинаковыми некоторыми полями, так, что их можно сравнивать между собой.&lt;br /&gt;
(при условии, что типы этих полей сравнимы).&lt;br /&gt;
&lt;br /&gt;
И вот это "сравнимы" я попытался записать готовыми концептами std::equality_comparable и std::equality_comparable_with&lt;br /&gt;
&lt;br /&gt;
Дистиллированный пример выглядит так&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;&lt;span class='kw'&gt;namespace&lt;/span&gt; aha {
    &lt;span class='com'&gt;// пусть есть несколько разных структур
    // некоторые из которых сравнимы между собой ad-hoc&lt;/span&gt;

    &lt;span class='kw'&gt;struct&lt;/span&gt; foo { &lt;span class='kw'&gt;bool operator&lt;/span&gt; == (&lt;span class='kw'&gt;const&lt;/span&gt; foo&amp;amp;) &lt;span class='kw'&gt;const&lt;/span&gt; = &lt;span class='kw'&gt;default&lt;/span&gt;; };
    &lt;span class='kw'&gt;struct&lt;/span&gt; bar { &lt;span class='kw'&gt;bool operator&lt;/span&gt; == (&lt;span class='kw'&gt;const&lt;/span&gt; bar&amp;amp;) &lt;span class='kw'&gt;const&lt;/span&gt; = &lt;span class='kw'&gt;default&lt;/span&gt;; };
    &lt;span class='kw'&gt;struct&lt;/span&gt; buz { };

    &lt;span class='kw'&gt;bool operator&lt;/span&gt; == (bar &lt;span class='kw'&gt;const&lt;/span&gt;&amp;amp;, foo &lt;span class='kw'&gt;const&lt;/span&gt;&amp;amp;) { &lt;span class='kw'&gt;return true&lt;/span&gt;; }
    &lt;span class='kw'&gt;bool operator&lt;/span&gt; == (foo &lt;span class='kw'&gt;const&lt;/span&gt;&amp;amp;, bar &lt;span class='kw'&gt;const&lt;/span&gt;&amp;amp;) { &lt;span class='kw'&gt;return true&lt;/span&gt;; }

    &lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;&lt;span class='kw'&gt;class&lt;/span&gt; T&amp;gt; concept Family = std::same_as&amp;lt;T,foo&amp;gt; || std::same_as&amp;lt;T,bar&amp;gt; || std::same_as&amp;lt;T,buz&amp;gt;;

    &lt;span class='com'&gt;// и обёртка над типом из этого семейства&lt;/span&gt;
    &lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;Family T&amp;gt; &lt;span class='kw'&gt;struct&lt;/span&gt; wrapper {
        T t;
        &lt;span class='kw'&gt;bool operator&lt;/span&gt; == (wrapper &lt;span class='kw'&gt;const&lt;/span&gt;&amp;amp;) &lt;span class='kw'&gt;const&lt;/span&gt;
            requires std::equality_comparable&amp;lt;T&amp;gt;
            = &lt;span class='kw'&gt;default&lt;/span&gt;;
        &lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;Family U&amp;gt;
        &lt;span class='kw'&gt;bool operator&lt;/span&gt; == (wrapper&amp;lt;U&amp;gt; &lt;span class='kw'&gt;const&lt;/span&gt;&amp;amp; other) &lt;span class='kw'&gt;const&lt;/span&gt;
            requires std::equality_comparable_with&amp;lt;T, U&amp;gt;
            { &lt;span class='kw'&gt;return&lt;/span&gt; t == other.t; }
    };
}

static_assert(std::equality_comparable&amp;lt;aha::foo&amp;gt;);
static_assert(std::equality_comparable&amp;lt;aha::bar&amp;gt;);

static_assert(std::equality_comparable&amp;lt;aha::wrapper&amp;lt;aha::bar&amp;gt;&amp;gt;);

&lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;&lt;span class='kw'&gt;class&lt;/span&gt; T, &lt;span class='kw'&gt;class&lt;/span&gt; U&amp;gt; concept ad_hoc_comparable = requires(std::decay_t&amp;lt;T&amp;gt; t, std::decay_t&amp;lt;U&amp;gt; u) { t==u; t!=u; };

static_assert(ad_hoc_comparable&amp;lt;aha::foo, aha::bar&amp;gt;);
static_assert(std::equality_comparable_with&amp;lt;aha::foo, aha::bar&amp;gt;);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
И вот оказалось, что фиг вам.&lt;br /&gt;
equality_comparable_with зачем-то требует common_reference_t, который в свою очередь требует (специализации) basic_common_reference.&lt;br /&gt;
&lt;br /&gt;
Окей, сделал кастомизацию, как это советуют на cppreference&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;&lt;span class='kw'&gt;namespace&lt;/span&gt; std {
    &lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;
        aha::Family T, aha::Family U,
        &lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;&lt;span class='kw'&gt;class&lt;/span&gt;&amp;gt;&lt;span class='kw'&gt;class&lt;/span&gt; TQ,
        &lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;&lt;span class='kw'&gt;class&lt;/span&gt;&amp;gt;&lt;span class='kw'&gt;class&lt;/span&gt; UQ
    &amp;gt;
    &lt;span class='kw'&gt;struct&lt;/span&gt; basic_common_reference&amp;lt;T, U, TQ, UQ&amp;gt; {
        &lt;span class='kw'&gt;using&lt;/span&gt; type = &lt;span class='kw'&gt;void&lt;/span&gt;;
    };
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
и всё равно не работает, потому что&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;static_assert(std::convertible_to&amp;lt;aha::foo, &lt;span class='kw'&gt;void&lt;/span&gt;&amp;gt;);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
не может привести const aha::foo&amp;amp; к void.&lt;br /&gt;
&lt;br /&gt;
WTF?! ЧЯДНТ?&lt;br /&gt;
Не хотелось бы плодить вспомогательные сущности ad_hoc_comparable, когда есть готовые...&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Thu, 04 Jun 2026 12:11:47 GMT</pubDate>
		
			<author>Кодт &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>8</slash:comments>
		
	</item>

	<item>
		<title>cppreference совсем закрыли ?</title>
		<link>http://rsdn.org/Forum/cpp/9095481.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9095481</guid>
		<comments>http://rsdn.org/Forum/cpp/9095481</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9095481</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9095481</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9095481</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;Я некоторое время ходил на cppreference.dev&lt;br /&gt;
Но сегодня и он недоступен. &lt;br /&gt;
А также ru.cppreference.net&lt;br /&gt;
&lt;br /&gt;
Кто-нить еще знает адреса другие ?&lt;br /&gt;
Очень уж полезный ресурс.&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Tue, 02 Jun 2026 05:35:49 GMT</pubDate>
		
			<author>LaptevVV &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>10</slash:comments>
		
	</item>

	<item>
		<title>выделение памяти в constexpr</title>
		<link>http://rsdn.org/Forum/cpp/9094691.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9094691</guid>
		<comments>http://rsdn.org/Forum/cpp/9094691</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9094691</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9094691</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9094691</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;Я чего-то не понимаю, почему такие разные ошибки для constexpr std::string и constexpr std::vector.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;constexpr std::string sabcd = &lt;span class='str'&gt;"abc"&lt;/span&gt;; &lt;span class='com'&gt;// строка может быть труъ constexpr&lt;/span&gt;
static_assert(sabcd == &lt;span class='str'&gt;"abc"&lt;/span&gt;);

constexpr &lt;span class='kw'&gt;auto&lt;/span&gt; sabc = []{
    std::string s;
    s.push_back(&lt;span class='str'&gt;'a'&lt;/span&gt;);
    s.push_back(&lt;span class='str'&gt;'b'&lt;/span&gt;);
    s.push_back(&lt;span class='str'&gt;'c'&lt;/span&gt;);
    &lt;span class='kw'&gt;return&lt;/span&gt; s;
};
static_assert(sabc() == &lt;span class='str'&gt;"abc"&lt;/span&gt;); &lt;span class='com'&gt;// лямбда со строкой наружу - тоже может быть труъ&lt;/span&gt;
constexpr &lt;span class='kw'&gt;auto&lt;/span&gt; sabcv = sabc(); &lt;span class='com'&gt;// а вот её результат уже не труъ&lt;/span&gt;
static_assert(sabcv == &lt;span class='str'&gt;"abc"&lt;/span&gt;); &lt;span class='com'&gt;// ОШИБКА&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;test.cpp:607:21: error: non-constant condition for static assertion
  607 | static_assert(sabcv == "abc");
      |               ~~~~~~^~~~~~~~
test.cpp:607:21:   in ‘constexpr’ expansion of ‘std::operator==&amp;lt;char, char_traits&amp;lt;char&amp;gt;, allocator&amp;lt;char&amp;gt; &amp;gt;(sabcv, ((const char*)"abc"))’
/usr/include/c++/13/bits/basic_string.h:3730:24:   in ‘constexpr’ expansion of ‘(&amp;amp; __lhs)-&amp;gt;std::__cxx11::basic_string&amp;lt;char&amp;gt;::size()’
test.cpp:607:21: error: the value of ‘sabcv’ is not usable in a constant expression
test.cpp:606:16: note: ‘sabcv’ used in its own initializer
  606 | constexpr auto sabcv = sabc();
      |                ^~~~~&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;constexpr &lt;span class='kw'&gt;auto&lt;/span&gt; vabc = []{
    std::vector&amp;lt;&lt;span class='kw'&gt;char&lt;/span&gt;&amp;gt; v;
    v.push_back(&lt;span class='str'&gt;'a'&lt;/span&gt;);
    v.push_back(&lt;span class='str'&gt;'b'&lt;/span&gt;);
    v.push_back(&lt;span class='str'&gt;'c'&lt;/span&gt;);
    &lt;span class='kw'&gt;return&lt;/span&gt; v;
};
static_assert(vabc().size() == 3); &lt;span class='com'&gt;// лямбда с вектором - труъ&lt;/span&gt;

constexpr &lt;span class='kw'&gt;auto&lt;/span&gt; vabcv = vabc(); &lt;span class='com'&gt;// а тут прямо сразу ОШИБКА&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;/usr/include/c++/13/bits/allocator.h:195:52: error: ‘&amp;lt;lambda()&amp;gt;()’ is not a constant expression because it refers to a result of ‘operator new’
  195 |             return static_cast&amp;lt;_Tp*&amp;gt;(::operator new(__n));
      |                                      ~~~~~~~~~~~~~~^~~~~&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Sat, 30 May 2026 20:50:30 GMT</pubDate>
		
			<author>Кодт &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>2</slash:comments>
		
	</item>

	<item>
		<title>Композиции, третий подход к снаряду!</title>
		<link>http://rsdn.org/Forum/cpp/9093848.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9093848</guid>
		<comments>http://rsdn.org/Forum/cpp/9093848</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9093848</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9093848</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9093848</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;Когда я внедрил идею с резолвером к себе в ненормальное, то столкнулся с неприятным явлением.&lt;br /&gt;
В ненормальном у меня есть списки альтернатив порядка 100 штук, и опрашиваются они порядка 500 раз.&lt;br /&gt;
Это приводит к тому, что получается шлемюэлева туча типов&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;&lt;span class='kw'&gt;class&lt;/span&gt; resolver&amp;lt;A1, typelist&amp;lt;&amp;gt;, F1, ..., F100&amp;gt; : &lt;span class='kw'&gt;public
class&lt;/span&gt; resolver&amp;lt;A1, typelist&amp;lt;F1&amp;gt;, F2, ..., F100&amp;gt; : &lt;span class='kw'&gt;public&lt;/span&gt;
.....
resolver&amp;lt;A1, typelist&amp;lt;F1,...,F50&amp;gt;, F51, F52,..., F100&amp;gt; &lt;span class='com'&gt;// допустим, F51 подошла&lt;/span&gt;
{
A2 &lt;span class='kw'&gt;operator&lt;/span&gt;()(A1 a, F1,...,F50, F51 f, F52,...,F100) &lt;span class='kw'&gt;const&lt;/span&gt; { &lt;span class='kw'&gt;return&lt;/span&gt; f(a); }
};

&lt;span class='kw'&gt;class&lt;/span&gt; resolver&amp;lt;A2, typelist&amp;lt;&amp;gt;, F1, ..., F100&amp;gt; : &lt;span class='com'&gt;// и так далее&lt;/span&gt;
.....
&lt;span class='kw'&gt;class&lt;/span&gt; resolver&amp;lt;A500, typelist&amp;lt;&amp;gt;, F1, ..., F100&amp;gt; : &lt;span class='com'&gt;// и так далее&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Для каждого типа аргумента у нас этажерка из O(Nfuns) пустых, слава богу, структур &amp;mdash; но у каждой из них O(Nfuns) параметров!&lt;br /&gt;
&lt;br /&gt;
Компиляция улетает в небеса. (При том, что я переписал резолвер под конкретику ненормального).&lt;br /&gt;
&lt;br /&gt;
Поэтому я вернулся обратно к старым добрым fold expressions.&lt;br /&gt;
&lt;br /&gt;
В обобщённом коде это выглядит так.&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;&lt;span class='com'&gt;// концепт, проверяющий критерий&lt;/span&gt;
&lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;&lt;span class='kw'&gt;class&lt;/span&gt; T, CRITERIA C&amp;gt;
concept fits_criteria = C&amp;lt;T&amp;gt;::value;

&lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;&lt;span class='kw'&gt;class&lt;/span&gt; F, CRITERIA C, &lt;span class='kw'&gt;class&lt;/span&gt; A&amp;gt;
concept appropriate_alternative = Callable&amp;lt;F&amp;gt; &amp;amp;&amp;amp; fits_criteria&amp;lt;std::invoke_result_t&amp;lt;F, A&amp;gt;, C&amp;gt;;
&lt;span class='com'&gt;// 1) можно вызвать
// 2) и результат подходит под критерий остановки


// успешный результат поиска функции - это обёртка-ссылка на эту функцию&lt;/span&gt;
&lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;Callable F&amp;gt; &lt;span class='kw'&gt;struct&lt;/span&gt; solution {
    &lt;span class='kw'&gt;static&lt;/span&gt; constexpr &lt;span class='kw'&gt;bool&lt;/span&gt; value = &lt;span class='kw'&gt;true&lt;/span&gt;;
    F f; &lt;span class='com'&gt;// ссылка

    // отбрасываем хвост свёртки&lt;/span&gt;
    constexpr &lt;span class='kw'&gt;auto operator&lt;/span&gt; || (&lt;span class='kw'&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; g) &lt;span class='kw'&gt;const&lt;/span&gt; { &lt;span class='kw'&gt;return&lt;/span&gt; *&lt;span class='kw'&gt;this&lt;/span&gt;; }

    &lt;span class='com'&gt;// вызов аргумента (который априори уже подошёл)&lt;/span&gt;
    constexpr decltype(&lt;span class='kw'&gt;auto&lt;/span&gt;) &lt;span class='kw'&gt;operator&lt;/span&gt;()(&lt;span class='kw'&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; a) &lt;span class='kw'&gt;const&lt;/span&gt; {
        &lt;span class='kw'&gt;return&lt;/span&gt; FFWD(f, a);
    }
};

&lt;span class='com'&gt;// затравка поиска подходящей функции
// (такой, что C&amp;lt; decltype(f(a)) &amp;gt;)&lt;/span&gt;
&lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;CRITERIA C, &lt;span class='kw'&gt;class&lt;/span&gt; A&amp;gt; &lt;span class='kw'&gt;struct&lt;/span&gt; seed {
    &lt;span class='kw'&gt;static&lt;/span&gt; constexpr &lt;span class='kw'&gt;bool&lt;/span&gt; value = &lt;span class='kw'&gt;false&lt;/span&gt;;

    constexpr &lt;span class='kw'&gt;auto operator&lt;/span&gt; || (&lt;span class='kw'&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; f) &lt;span class='kw'&gt;const&lt;/span&gt; {
        &lt;span class='kw'&gt;using&lt;/span&gt; F = decltype(f);
        &lt;span class='kw'&gt;if&lt;/span&gt; constexpr (appropriate_alternative&amp;lt;F, C, A&amp;gt;)
            &lt;span class='kw'&gt;return&lt;/span&gt; solution&amp;lt;F&amp;gt;{FWD(f)};
        &lt;span class='kw'&gt;else
            return&lt;/span&gt; *&lt;span class='kw'&gt;this&lt;/span&gt;;
    }
};

&lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;CRITERIA C&amp;gt; &lt;span class='kw'&gt;struct&lt;/span&gt; run_alternatives {
    constexpr &lt;span class='kw'&gt;auto&lt;/span&gt; get_alternative(&lt;span class='kw'&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; a, Callable &lt;span class='kw'&gt;auto&lt;/span&gt;&amp;amp;&amp;amp;... fs) &lt;span class='kw'&gt;const&lt;/span&gt; {
        &lt;span class='kw'&gt;return&lt;/span&gt; ( seed&amp;lt;C, decltype(a)&amp;gt;{} || ... || FWD(fs) );
    }
    constexpr decltype(&lt;span class='kw'&gt;auto&lt;/span&gt;) &lt;span class='kw'&gt;operator&lt;/span&gt;()(&lt;span class='kw'&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; a, Callable &lt;span class='kw'&gt;auto&lt;/span&gt;&amp;amp;&amp;amp;... fs) &lt;span class='kw'&gt;const&lt;/span&gt;
    RETURN_IF_RESOLVED(
        get_alternative(FWD(a), FWD(fs)...) (FWD(a))
    )
};&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Тут у нас для каждого аргумента 1 seed, 1 solution и O(Nfuns) операторов ||&lt;br /&gt;
&amp;mdash; &amp;lt;C,A,F&amp;gt;(seed&amp;lt;C,A&amp;gt;, F) &amp;mdash; для всех F, которые ещё не подошли&lt;br /&gt;
&amp;mdash; &amp;lt;F,G&amp;gt;(solution&amp;lt;F&amp;gt;, G) &amp;mdash; где F,G &amp;mdash; пара смежных функций, а не все со всеми&lt;br /&gt;
&lt;br /&gt;
Компилятору это кажется гораздо меньшей проблемой.&lt;br /&gt;
Опять же, операторы смежных пар инстанцируются ровно один раз.&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Thu, 28 May 2026 01:44:31 GMT</pubDate>
		
			<author>Кодт &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>5</slash:comments>
		
	</item>

	<item>
		<title>Композиции, reloaded</title>
		<link>http://rsdn.org/Forum/cpp/9092906.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9092906</guid>
		<comments>http://rsdn.org/Forum/cpp/9092906</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9092906</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9092906</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9092906</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;Ветка "как посокращать конструкторы" шибко выросла&lt;br /&gt;
&lt;a class=" tips m" href="https://rsdn.org/forum/cpp/9091851.flat#9091851" rel="#ElwpmO" target="_blank" title="как посокращать конструкторы?"&gt;https://rsdn.ru/forum/cpp/9091851.flat#9091851&lt;div class="tooltip" id="ElwpmO"&gt;Автор: Кодт&lt;br /&gt;Дата: 22.05 20:02&lt;/div&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Поэтому хочу предложить вот такое резюме.&lt;br /&gt;
&lt;br /&gt;
Как совсем-совсем идеально передавать аргументы и возвращать результаты двух видов композиций&lt;br /&gt;
&amp;mdash; список альтернатив (выполнить первую подходящую по совместимости аргумента и критерию результата)&lt;br /&gt;
&amp;mdash; цепочка (выполнить до отсечки по несовместимости аргумента или критерию результата)&lt;br /&gt;
&lt;br /&gt;
Творчески переработал идеи, выдвинутые товарищем &lt;a class="m" href="https://rsdn.org/account/info/49596" target="_blank" title=""&gt;rg45&lt;/a&gt;&lt;br /&gt;
и сделал такой код.&lt;br /&gt;
Он длинный, поэтому см. гитхаб.&lt;br /&gt;
Хедер &lt;a class="github m" href="https://github.com/nickolaym/cpp-fun/blob/main/single-files/compose.h" target="_blank"&gt;https://github.com/nickolaym/cpp-fun/blob/main/single-files/compose.h&lt;/a&gt;&lt;br /&gt;
и юниттесты &lt;a class="github m" href="https://github.com/nickolaym/cpp-fun/blob/main/single-files/compose.cpp" target="_blank"&gt;https://github.com/nickolaym/cpp-fun/blob/main/single-files/compose.cpp&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Альтернативы ассоциативны,&lt;br /&gt;
то есть, допустим, у нас есть функции f, g, h, i, j, k,&lt;br /&gt;
и f и g не подошли, а h подошла (и по аргументу, и по результату),&lt;br /&gt;
в этом случае мы с любого уровня вложенности вернём h(x) и не станем рассматривать альтернативы позади неё.&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;seq(f, g,     h, i, j,  k )(x) = h(x)
seq(f, g, seq(h, i, j,  k))(x) = h(x)
seq(f, g, seq(h, i, j), k )(x) = h(x)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Цепочка по-прежнему не обладает свойством ассоциативности,&lt;br /&gt;
то есть, допустим, у нас есть функции f, g, h, i, j, k&lt;br /&gt;
и мы прерываемся на h из-за того, что тип, возвращаемый из h, не влезает в i.&lt;br /&gt;
в этом случае мы вылезем на внешний уровень, а там окажется следующий шаг k, в который может влезть результат.&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;seq(f, g,     h, i, j,  k )(x) =   h(g(f(x)))
seq(f, g, seq(h, i, j,  k))(x) =   h(g(f(x)))
seq(f, g, seq(h, i, j), k )(x) = k(h(g(f(x))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Но если ограничить предметную область условием, что критерий "не влезает в следующую функцию" совпадает с предметным "это искомый результат"&lt;br /&gt;
(безотносительно того, какую роль в этом играет явный критерий остановки &amp;mdash; параметр шаблона),&lt;br /&gt;
то ассоциативность выполнится.&lt;br /&gt;
То есть, если h(g(f(x))) не влезло в i, то оно не должно влезть и в k.&lt;br /&gt;
Либо же, если оно не влезло, то оно же подпало под критерий остановки, &amp;mdash; в таком случае оно и этажом выше подпадёт под критерий остановки.&lt;br /&gt;
&lt;br /&gt;
(Договорившись об этом, я вполне могу делать циклы for и while в своих ненормальных алгорифмах! Ура...)&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Mon, 25 May 2026 15:55:40 GMT</pubDate>
		
			<author>Кодт &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>22</slash:comments>
		
	</item>

	<item>
		<title>как посокращать конструкторы?</title>
		<link>http://rsdn.org/Forum/cpp/9091851.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9091851</guid>
		<comments>http://rsdn.org/Forum/cpp/9091851</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9091851</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9091851</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9091851</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;Продолжаю пилить свои ненормальные алгорифмы &lt;a class="github m" href="https://github.com/nickolaym/nenormal" target="_blank"&gt;https://github.com/nickolaym/nenormal&lt;/a&gt;&lt;br /&gt;
и захотел минимизировать количество move-конструкторов рантаймовых типов.&lt;br /&gt;
&lt;br /&gt;
Для того, чтобы скрестить рантайм с компайл-таймом, ну, не буду сейчас тут расписывать подробности,&lt;br /&gt;
я завёл несколько обёрток с семантикой функции.&lt;br /&gt;
&lt;br /&gt;
Если упрощать, то это выглядит вот так&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;&lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;&lt;span class='kw'&gt;class&lt;/span&gt; T, &lt;span class='kw'&gt;class&lt;/span&gt; A&amp;gt; &lt;span class='kw'&gt;struct&lt;/span&gt; augmented_text {
  T text; &lt;span class='com'&gt;// чистый компайл-тайм&lt;/span&gt;
  A aux; &lt;span class='com'&gt;// потенциально рантайм&lt;/span&gt;
};
&lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;&lt;span class='kw'&gt;class&lt;/span&gt; X&amp;gt; concept AugmentedText = ..... remove_cvref_t&amp;lt;X&amp;gt; = augmented_text&amp;lt;T,A&amp;gt; .....;

AugmentedText &lt;span class='kw'&gt;auto&lt;/span&gt; long_recursive_operation(AugmentedText &lt;span class='kw'&gt;auto&lt;/span&gt;&amp;amp;&amp;amp; arg) {
  .....
  &lt;span class='kw'&gt;return&lt;/span&gt; yet_another_long_recursion_operation(
    augmented_text{
      .text = new_text,
      .aux = arg.aux(.....), &lt;span class='com'&gt;// вычисляет своё следующее значение&lt;/span&gt;
    }
  )
  .....
};&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Одна из обёрток &amp;mdash; это функция с внешним аккумулятором&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;&lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;&lt;span class='kw'&gt;class&lt;/span&gt; F, &lt;span class='kw'&gt;class&lt;/span&gt; A&amp;gt;
&lt;span class='kw'&gt;struct&lt;/span&gt; cumulative_effect {
  F f;
  A a;
  cumulative_effect &lt;span class='kw'&gt;operator&lt;/span&gt;()() &lt;span class='kw'&gt;const&lt;/span&gt; { &lt;span class='kw'&gt;return&lt;/span&gt; cumulative_effect{f, f(a)}; }
  &lt;span class='com'&gt;// дополнительные аргументы сейчас не буду подвёрстывать, чтоб не захламлять
  // равно как и изменчивость типа A&lt;/span&gt;
};&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
И вот тут у меня начались проблемки.&lt;br /&gt;
Для начала, нужно сделать две версии оператора() &amp;mdash; const&amp;amp; и &amp;amp;&amp;amp;.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;  cumulative_effect &lt;span class='kw'&gt;operator&lt;/span&gt;()() &amp;amp;&amp;amp; {
    A a1 = f(std::move(a)); &lt;span class='com'&gt;// сперва вычислили новый аккумулятор&lt;/span&gt;
    &lt;span class='kw'&gt;return&lt;/span&gt; cumulative_effect{
      std::move(f), &lt;span class='com'&gt;// затем в конструкторе F(F&amp;amp;&amp;amp;) перенесли содержимое f (инвалидировали this-&amp;gt;f)&lt;/span&gt;
      std::move(a1) &lt;span class='com'&gt;// и в конструкторе A(A&amp;amp;&amp;amp;) перенесли содержимое a1&lt;/span&gt;
    };
  }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Если просто написать&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;  &lt;span class='kw'&gt;return&lt;/span&gt; cumulative_effect{std::move(f), f &lt;span class='com'&gt;/* инвалидированное */&lt;/span&gt; (std::move(a)) };&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
получим неопределённое поведение.&lt;br /&gt;
&lt;br /&gt;
Ок. Можно сделать промежуточную функцию&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;  cumulative_effect rewrite(A&amp;amp;&amp;amp; a1) &amp;amp;&amp;amp; { &lt;span class='kw'&gt;return&lt;/span&gt; cumulative_effect{std::move(f), std::move(a)}; }
  cumulative_effect &lt;span class='kw'&gt;operator&lt;/span&gt;()() &amp;amp;&amp;amp; { &lt;span class='kw'&gt;return&lt;/span&gt; rewrite(f(std::move(a))); }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
но это &amp;mdash; размен шила на мыло.&lt;br /&gt;
&lt;br /&gt;
Можно пойти чуть дальше &amp;mdash; отложить вызов в конструктор&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;  cumulative_effect(do_it_tag, cumulative_effect&amp;amp;&amp;amp; old)
    : f(std::move(old.f))
    , a(&lt;span class='kw'&gt;this&lt;/span&gt;-&amp;gt;f(std::move(old.a))
  {}
  cumulative_effect &lt;span class='kw'&gt;operator&lt;/span&gt;()() &amp;amp;&amp;amp; { &lt;span class='kw'&gt;return&lt;/span&gt; cumulative_effect(do_it_tag{}, std::move(*&lt;span class='kw'&gt;this&lt;/span&gt;));  }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Но добавление конструктора уничтожает возможность агрегатной инициализации.&lt;br /&gt;
Это значит, что будет ещё и конструктор&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;  cumulative_effect(F&amp;amp;&amp;amp; f, A&amp;amp;&amp;amp; a)
    : f(std::move(f))
    , a(std::move(a))
  {}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
и значит, в точке создания стартового значения мы получим +1 перемещение функции и +1 перемещение аккумулятора.&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;&lt;br /&gt;
Как эту проблему я сейчас решил (ещё не закоммитил).&lt;br /&gt;
&lt;br /&gt;
Просто поменял местами поля в структуре.&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;&lt;span class='kw'&gt;template&lt;/span&gt;&amp;lt;&lt;span class='kw'&gt;class&lt;/span&gt; A, &lt;span class='kw'&gt;class&lt;/span&gt; F&amp;gt; &lt;span class='kw'&gt;struct&lt;/span&gt; cumulative_effect {
  A a;
  F f;
  &lt;span class='com'&gt;// инициализация - агрегатная, 0 промежуточных конструкторов&lt;/span&gt;

  cumulative_effect &lt;span class='kw'&gt;operator&lt;/span&gt;()()&amp;amp;&amp;amp; {
    &lt;span class='kw'&gt;return&lt;/span&gt; cumulative_effect{
      f(std::move(a)), &lt;span class='com'&gt;// передача a по ссылке, и пусть там f делает что хочет&lt;/span&gt;
      std::move(f), &lt;span class='com'&gt;// F(F&amp;amp;&amp;amp;)&lt;/span&gt;
    };
  }
};&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Из оператора, естественно, происходит copy elision, поэтому поля создаются в клиентском объекте.&lt;br /&gt;
Итого ровно 1 перемещение f и 0 перемещений нового аккумулятора.&lt;br /&gt;
&lt;br /&gt;
Но это потребовало поставить телегу впереди лошади.&lt;br /&gt;
Некрасивенько... Хотя, если так подумать, у меня там весь код в конвеерном стиле arg &amp;gt;&amp;gt; handler &amp;gt;&amp;gt; handler ....&lt;br /&gt;
&lt;br /&gt;
Но может быть, есть и другие способы? Какое-нибудь колдунство C++23, о котором я не подозреваю?&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Fri, 22 May 2026 17:02:00 GMT</pubDate>
		
			<author>Кодт &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>44</slash:comments>
		
	</item>

	<item>
		<title>Проверить все поля структуры</title>
		<link>http://rsdn.org/Forum/cpp/9090138.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9090138</guid>
		<comments>http://rsdn.org/Forum/cpp/9090138</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9090138</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9090138</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9090138</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;Есть ли в современном C++ способ сделать что-то со всеми полями произвольной структуры (предполагается, что они одного типа), например, проверить на равенство 0?&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Sun, 17 May 2026 15:19:54 GMT</pubDate>
		
			<author>Shtole &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>13</slash:comments>
		
	</item>

	<item>
		<title>ненормальные нормальные алгорифмы</title>
		<link>http://rsdn.org/Forum/cpp/9084560.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9084560</guid>
		<comments>http://rsdn.org/Forum/cpp/9084560</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9084560</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9084560</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9084560</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;Вот давеча LaptevVV спрашивал про constexpr, так у меня есть кое-чего.&lt;br /&gt;
Хочу показать свою заготовку.&lt;br /&gt;
Пилю библиотеку Нормальных Алгорифмов Маркова во время компиляции.&lt;br /&gt;
&lt;a class="github m" href="https://github.com/nickolaym/nenormal" target="_blank"&gt;https://github.com/nickolaym/nenormal&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Понятное дело, что это извращения с кодом, и вообще, когда допилю, (надеюсь, к Дню Программиста), сделаю статью на хабре.&lt;br /&gt;
Но сейчас мне просто нужна обратная связь по коду.&lt;br /&gt;
&lt;br /&gt;
Из TODO&lt;br /&gt;
&amp;mdash; обмазать всё пространствами имён&lt;br /&gt;
&amp;mdash; унифицировать имена и даже их стиль (там у меня и кемелКейс местами есть)&lt;br /&gt;
&amp;mdash; переписать доки, нормально осмыслить базис теории категорий, который там просвечивает, но вполсилы&lt;br /&gt;
&amp;mdash; сделать так, чтобы код одинаково хорошо работал и во время компиляции на уникальных типах, и во время исполнения на однородных&lt;br /&gt;
&amp;mdash; сделать аугментацию более универсальной (сейчас сигнатура колбеков зафиксирована, и вызываются они строго в определённых местах)&lt;br /&gt;
&amp;mdash; выкинуть неудачные подходы к снаряду, добавить удачные&lt;br /&gt;
&amp;mdash; сделать инструменты статического и динамического анализа машины (возможное зацикливание, ошибки, отчёты...)&lt;br /&gt;
&lt;br /&gt;
Пока всего этого нет, &amp;mdash; статьи тоже нет )))&lt;br /&gt;
Но я обещаю, будет!&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;&lt;br /&gt;
Что это и зачем&lt;br /&gt;
&lt;br /&gt;
1) НАМ &amp;mdash; абстрактная машина, представляющая последовательность правил поиска-и-замены подстрок. Состояние машины &amp;mdash; это строка.&lt;br /&gt;
Машина ищет первое подходящее правило и меняет первое вхождение искомой строки на заменную. Если правило не помечено, как финальное, то машина повторяет эту процедуру.&lt;br /&gt;
Если ничего не подошло, то состояние не изменилось и, очевидно, не изменится. Такое диагностируемое зацикливание также является финальным состоянием.&lt;br /&gt;
Можно сказать, что в конце НАМ-программы неявно стоит правило (""/"",стоп).&lt;br /&gt;
&lt;br /&gt;
2) Во время компиляции использовать динамические контейнеры можно ОЧЕНЬ ограниченно, поэтому сделал всё на чистых константах времени компиляции, для этого нужны зависимые типы.&lt;br /&gt;
&lt;br /&gt;
3) Циклы на полиморфных типах невозможны, поэтому сделано всё на рекурсии. Но рекурсия &amp;mdash; ограниченный ресурс компилятора (да и рантайма), поэтому применил лайфхаки по развёртыванию циклов.&lt;br /&gt;
&lt;br /&gt;
Сейчас машина допускает программы неограниченной длины (300 правил как нефиг делать), работающие не более 9000 итераций (глубина 900 помножить на развёртывание цикла на 10 шагов).&lt;br /&gt;
Увеличить время работы можно экспоненциально!!! (сделать цикл саморасширяемым), но это в конечном счёте убьёт компилятор.&lt;br /&gt;
&lt;br /&gt;
&lt;hr /&gt;&lt;br /&gt;
Пример программы&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;constexpr &lt;span class='kw'&gt;auto&lt;/span&gt; executor = machine_fun&amp;lt;
  rule_loop&amp;lt;
    rules&amp;lt;
      rule&amp;lt;str{&lt;span class='str'&gt;"hello"&lt;/span&gt;}, str{&lt;span class='str'&gt;"privet"&lt;/span&gt;}, regular_state&amp;gt;{},
      rule&amp;lt;str{&lt;span class='str'&gt;"world"&lt;/span&gt;}, str{&lt;span class='str'&gt;"mir"&lt;/span&gt;}, regular_state&amp;gt;{}
    &amp;gt;{}
  &amp;gt;{}
&amp;gt;{};
&lt;span class='com'&gt;// правила внесены как аргументы шаблона, а не как члены кортежа. всё равно типы зависимые, поэтому члены-данные - избыточны&lt;/span&gt;

constexpr &lt;span class='kw'&gt;auto&lt;/span&gt; input_value = str{&lt;span class='str'&gt;"hello world!"&lt;/span&gt;}; &lt;span class='com'&gt;// строка времени компиляции - здесь это константный массив (длина выведена из литерала)&lt;/span&gt;
constexpr &lt;span class='kw'&gt;auto&lt;/span&gt; input = ct&amp;lt;input_value&amp;gt;{};         &lt;span class='com'&gt;// константа времени компиляции с уникальным типом&lt;/span&gt;

constexpr &lt;span class='kw'&gt;auto&lt;/span&gt; result = executor(input); &lt;span class='com'&gt;// в constexpr-функцию (operator()) передали истинную константу и получили на выходе истинную константу&lt;/span&gt;
constexpr &lt;span class='kw'&gt;auto&lt;/span&gt; result_value = result.value; &lt;span class='com'&gt;// сама строка лежит в статической константе&lt;/span&gt;

static_assert(result_value == str{&lt;span class='str'&gt;"privet mir!"&lt;/span&gt;});&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
В порядке безумия я там даже умножение и деление на марковских алгорифмах забабахал. Последовательность Коллаца.&lt;br /&gt;
Работает! Только компилируется около полутора минут.&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Fri, 01 May 2026 20:23:33 GMT</pubDate>
		
			<author>Кодт &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>3</slash:comments>
		
	</item>
</channel>
</rss>
