<?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, 31 May 2026 20:47:21 GMT</lastBuildDate>
    <ttl>5</ttl>
	<item>
		<title>Назначение кода времени компиляции и альтернативы</title>
		<link>http://rsdn.org/Forum/cpp/9094702.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9094702</guid>
		<comments>http://rsdn.org/Forum/cpp/9094702</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9094702</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9094702</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9094702</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;Такой вопрос.&lt;br /&gt;
&lt;br /&gt;
Начиналось вроде безобидно &amp;mdash; просто шаблоны с ограничениями. Вроде разумно.&lt;br /&gt;
&lt;br /&gt;
Далее, оказалось что с помощью SFINAE и прочих трюков имеем тьюринг-полный ЯП времени компиляции, пусть и не удобный. Оно вроде не задумывалось, но люди юзали.&lt;br /&gt;
&lt;br /&gt;
Далее добавили еще больше ништяков для времени компиляции &amp;mdash; и концепты и даже память теперь возможно выделять динамически (с оговорками). Но при этом доступа к системе нет и все выглядит немного как костыль.&lt;br /&gt;
&lt;br /&gt;
И кажется что какой-то архитектурный просчет произошел.&lt;br /&gt;
&lt;br /&gt;
Вот в Rust &amp;mdash; сразу макрос имеет доступ к коду, а proc_macro &amp;mdash; даже может создавать файлы на диске. Т.е. вообще нет ограничений на удобную кодогенерацию. Можно сделать что угодно, хоть любой сериализатор &amp;mdash; по JSON генерить структуры хоть что хочешь.&lt;br /&gt;
&lt;br /&gt;
В C++ как-то не очень ясно, вроде изначально задумывалось как шабоны и проверки времени компиляции. Но сейчас уже нет, уже полноценный ЯП, но без досупа к системе, без доступа даже к коду исходному. И как бы ни в тын ни в ворота.&lt;br /&gt;
&lt;br /&gt;
Кто может объяснить философию и назначение компилтайма именно C++ -версии.&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Sat, 30 May 2026 21:12:58 GMT</pubDate>
		
			<author>Shmj &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>36</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="#aOgoxh" target="_blank" title="как посокращать конструкторы?"&gt;https://rsdn.ru/forum/cpp/9091851.flat#9091851&lt;div class="tooltip" id="aOgoxh"&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>20</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>

	<item>
		<title>iota_view::iterator не двунаправленный</title>
		<link>http://rsdn.org/Forum/cpp/9068225.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9068225</guid>
		<comments>http://rsdn.org/Forum/cpp/9068225</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9068225</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9068225</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9068225</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;всем привет. Такая проблема.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class='c'&gt;&lt;code&gt;&lt;span class='kw'&gt;const auto&lt;/span&gt; fpsRange = std::ranges::iota_view(1, 32);
&lt;span class='kw'&gt;auto&lt;/span&gt; it = fpsRange.begin();
std::advance(it, 100); &lt;span class='com'&gt;// Ok&lt;/span&gt;
std::advance(it, -10); &lt;span class='com'&gt;// UB&lt;/span&gt;&lt;/code&gt;&lt;/pre&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;const auto&lt;/span&gt; testFps = [](&lt;span class='kw'&gt;int&lt;/span&gt; fps) { &lt;span class='kw'&gt;return&lt;/span&gt; fps &amp;lt; 15; };
&lt;span class='kw'&gt;auto&lt;/span&gt; it = std::ranges::lower_bound(fpsRange, &lt;span class='kw'&gt;true&lt;/span&gt;, std::ranges::less{}, [&amp;amp;](&lt;span class='kw'&gt;int&lt;/span&gt; fps){ &lt;span class='kw'&gt;return&lt;/span&gt; !testFps(fps); });&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Сейчас он уверенно виснет.&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Thu, 19 Mar 2026 15:35:31 GMT</pubDate>
		
			<author>sergii.p &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>10</slash:comments>
		
	</item>

	<item>
		<title>Операции сравнения</title>
		<link>http://rsdn.org/Forum/cpp/9060191.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9060191</guid>
		<comments>http://rsdn.org/Forum/cpp/9060191</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9060191</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9060191</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9060191</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;Вот завели в С++20 операцию трехстороннего сравнения. &lt;br /&gt;
Компилятор при ее реализации в классе генерит на ее основе правильные логические выражения с обычными операция сравнения. &lt;br /&gt;
&lt;br /&gt;
А если трехстороннее сравнение не определено в классе, чего тогда делается ?&lt;br /&gt;
Понятно, что равенство и неравенство можно сгенерить (но и тут есть нюансы). &lt;br /&gt;
А операция МЕНЬШЕ &amp;mdash; генерится ?&lt;br /&gt;
И какой из трех вариантов порядка соблюдается ?&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Thu, 26 Feb 2026 08:47:46 GMT</pubDate>
		
			<author>LaptevVV &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>8</slash:comments>
		
	</item>

	<item>
		<title>Уроки по написанию компилятора на C++</title>
		<link>http://rsdn.org/Forum/cpp/9059612.1</link>
		<guid isPermaLink="true">http://rsdn.org/Forum/cpp/9059612</guid>
		<comments>http://rsdn.org/Forum/cpp/9059612</comments>
		<wfw:comment>http://rsdn.org/Forum/PostRssComment.aspx?mid=9059612</wfw:comment>
		<wfw:commentRss>http://rsdn.org/Forum/RSS/9059612</wfw:commentRss>
		<trackback:ping>http://rsdn.org/Forum/Trackback.aspx?mid=9059612</trackback:ping>
		<description>
			
					&lt;div style="@import url(http://rsdn.org/Forum/Forum.css);"&gt;Шесть часов видео для интересующихся основами создания компиляторов.&lt;br /&gt;
&lt;br /&gt;
Юрий Минаев, архитектор компании PVS-Studio, записал 10 практических видеоуроков по написанию компилятора на языке С++. Это компилятор для выдуманного языка, который, впрочем, сильно смахивает на C.&lt;br /&gt;
&lt;br /&gt;
Бесплатные уроки: &lt;a class="m" href="https://pvs-studio.ru/ru/blog/training/courses/davajte-sozdadim-yazyk-programmirovaniya/" target="_blank"&gt;Давайте создадим язык программирования&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Составить впечатление о том, что вас ждёт, поможет эта &lt;a class="m" href="https://vkvideo.ru/video-11805870_456239700" target="_blank"&gt;видеонарезка&lt;/a&gt;.&lt;/div&gt;
				
		</description>
		
		<category>cpp</category>
		<pubDate>Tue, 24 Feb 2026 10:54:56 GMT</pubDate>
		
			<author>Analytic2007 &lt;forum@rsdn.org&gt;</author>
		
		
			<slash:comments>4</slash:comments>
		
	</item>
</channel>
</rss>
