breathe-doc / breathe

ReStructuredText and Sphinx bridge to Doxygen
https://breathe-doc.org
Other
751 stars 198 forks source link

Support for requires clauses is missing #482

Open mpusz opened 4 years ago

mpusz commented 4 years ago

Please provide support for C++20 requires clauses and requires expressions.

vermeeren commented 4 years ago

Possibly support needs to be provided in Sphinx.

Patches are as always very welcome, there is a shortage of contributors.

mpusz commented 4 years ago

I will do my best, but as I wrote in another thread I suck in Python ;-)

jakobandersen commented 4 years ago

@melvinvermeeren is correct, Sphinx does not yet support requires clauses or requires expressions, so please open an issue over there (perhaps one for each, as they don't overlap in implementation anyway). As with most features, they are mostly implemented when someone needs them, so it would be great if you can provide examples so we can aim at making them work first.

mpusz commented 4 years ago

Done: sphinx-doc/sphinx#7295, sphinx-doc/sphinx#7296.

You can find a lot of examples in my repo https://github.com/mpusz/units and its docs https://mpusz.github.io/units/index.html. For example this file: https://github.com/mpusz/units/blob/master/src/include/units/quantity.h.

jakobandersen commented 4 years ago

Regarding requires clauses and https://github.com/sphinx-doc/sphinx/issues/7295#issuecomment-629810549. I just tried a small example:

template<Quantity To, typename D, typename U, typename Rep>
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q) requires QuantityOf<To, D>;

and with Doxygen 1.8.13 the problem is definitely in the generated XML:

<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.13">
  <compounddef id="test_8hpp" kind="file" language="C++">
    <compoundname>test.hpp</compoundname>
      <sectiondef kind="var">
      <memberdef kind="variable" id="test_8hpp_1a948d5c478709883883d2719721a89997" prot="public" static="no" mutable="no">
        <type>constexpr auto</type>
        <definition>constexpr auto D</definition>
        <argsstring></argsstring>
        <name>D</name>
        ...
      </memberdef>
      </sectiondef>
      <sectiondef kind="func">
      <memberdef kind="function" id="test_8hpp_1a08bd15b592e647dd1a08c72c45d51934" prot="public" static="no" const="no" explicit="no" inline="no" virt="non-virtual">
        <templateparamlist>
          <param>
            <type>Quantity</type>
            <declname>To</declname>
            <defname>To</defname>
          </param>
          <param>
            <type>typename D</type>
          </param>
          <param>
            <type>typename U</type>
          </param>
          <param>
            <type>typename Rep</type>
          </param>
        </templateparamlist>
        <type>constexpr auto</type>
        <definition>constexpr auto quantity_cast</definition>
        <argsstring>(const quantity&lt; D, U, Rep &gt; &amp;q) requires QuantityOf&lt; To</argsstring>
        <name>quantity_cast</name>
        <param>
          <type>const quantity&lt; D, U, Rep &gt; &amp;</type>
          <declname>q</declname>
        </param>
        ...
      </memberdef>
      </sectiondef>
    ...
  </compounddef>
</doxygen>

The missing part of the requires clause has been put into an extra variable declaration constexpr auto D. Perhaps a newer version gives a different result?

mpusz commented 4 years ago

This is what I get for doxygen 1.8.17:

      <memberdef kind="function" id="namespaceunits_1aa6c00f741adb967299312a654a577e5a" prot="public" static="no" constexpr="yes" const="no" explicit="no" inline="no" virt="non-virtual">
        <templateparamlist>
          <param>
            <type>Quantity</type>
            <declname>To</declname>
            <defname>To</defname>
          </param>
          <param>
            <type>typename D</type>
          </param>
          <param>
            <type>typename U</type>
          </param>
          <param>
            <type>typename Rep</type>
          </param>
        </templateparamlist>
        <type>constexpr auto</type>
        <definition>constexpr auto units::quantity_cast</definition>
        <argsstring>(const quantity&lt; D, U, Rep &gt; &amp;q) requires QuantityOf&lt; To</argsstring>
        <name>quantity_cast</name>
        <param>
          <type>const <ref refid="classunits_1_1quantity" kindref="compound">quantity</ref>&lt; <ref refid="namespaceunits_1a84ee9cdfe11d0020084425cfceeda170" kindref="member">D</ref>, <ref refid="namespaceunits_1a36638878b7fc0a8fd9a238d36c6f107b" kindref="member">U</ref>, Rep &gt; &amp;</type>
          <declname>q</declname>
        </param>
        <briefdescription>
<para>Explcit cast of a quantity. </para>
        </briefdescription>
        <detaileddescription>
<para>Implicit conversions between quantities of different types are allowed only for &quot;safe&quot; (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.</para>
<para>This cast gets the target quantity type to cast to. For example:</para>
<para>auto q1 = <ref refid="namespaceunits_1aa6c00f741adb967299312a654a577e5a" kindref="member">units::quantity_cast</ref>&lt;<ref refid="namespaceunits_1_1physical_1_1si_1a86ff4b46eedd5d0bef7d950b762d957b" kindref="member">units::physical::si::time&lt;units::physical::si::second&gt;</ref>&gt;(1q_ms);</para>
<para><parameterlist kind="templateparam"><parameteritem>
<parameternamelist>
<parametername>To</parametername>
</parameternamelist>
<parameterdescription>
<para>a target quantity type to cast to</para>
</parameterdescription>
</parameteritem>
</parameterlist>
Implicit conversions between quantities of different types are allowed only for &quot;safe&quot; (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.</para>
<para>This cast gets only the target dimension to cast to. For example:</para>
<para>auto q1 = units::quantity_cast&lt;units::physical::si::acceleration&gt;(200q_Gal);</para>
<para><parameterlist kind="templateparam"><parameteritem>
<parameternamelist>
<parametername>ToD</parametername>
</parameternamelist>
<parameterdescription>
<para>a dimension type to use for a target quantity</para>
</parameterdescription>
</parameteritem>
</parameterlist>
Implicit conversions between quantities of different types are allowed only for &quot;safe&quot; (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.</para>
<para>This cast gets only the target unit to cast to. For example:</para>
<para>auto q1 = units::quantity_cast&lt;units::physical::si::second&gt;(1q_ms);</para>
<para><parameterlist kind="templateparam"><parameteritem>
<parameternamelist>
<parametername>ToU</parametername>
</parameternamelist>
<parameterdescription>
<para>a unit type to use for a target quantity</para>
</parameterdescription>
</parameteritem>
</parameterlist>
Implicit conversions between quantities of different types are allowed only for &quot;safe&quot; (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.</para>
<para>This cast gets only representation to cast to. For example:</para>
<para>auto q1 = units::quantity_cast&lt;int&gt;(1q_ms);</para>
<para><parameterlist kind="templateparam"><parameteritem>
<parameternamelist>
<parametername>ToRep</parametername>
</parameternamelist>
<parameterdescription>
<para>a representation type to use for a target quantity </para>
</parameterdescription>
</parameteritem>
</parameterlist>
</para>
        </detaileddescription>
        <inbodydescription>
        </inbodydescription>
        <location file="/home/mpusz/repos/units/src/include/units/quantity_cast.h" line="328" column="17" bodyfile="/home/mpusz/repos/units/src/include/units/quantity_cast.h" bodystart="390" bodyend="393"/>
      </memberdef>

for the following code:

https://github.com/mpusz/units/blob/5dd9eaac87a50adc62b170987ebac2d1344d63c5/src/include/units/quantity_cast.h#L315-L393

jakobandersen commented 4 years ago

I just tried with Doxygen 1.8.18 as well, and it gives the same result: the <argsstring> is incomplete and stops in the middle of the requires-clause. So I don't think Breathe can do any better for now.

svenevs commented 4 years ago

Upstream issue to track: https://github.com/doxygen/doxygen/issues/2732

Edit: see examples there for possible workarounds documenting them as interfaces.

mpusz commented 4 years ago

As I understand the workaround is for concepts definitions and does not apply to requires clauses?