:py:`func.is_conditional_noexcept` If the function is conditionally
:cpp:`noexcept`.
:py:`func.is_constexpr` If the function is :cpp:`constexpr`
+:py:`func.is_consteval` If the function is :cpp:`consteval`
:py:`func.is_defaulted` If the function is :cpp:`default`\ ed
:py:`func.is_deleted` If the function is :cpp:`delete`\ d
:py:`func.is_signal` If the function is a Qt signal. Set only
func.brief = parse_desc(state, element.find('briefdescription'))
func.description, templates, params, func.return_value, func.return_values, func.exceptions, search_keywords, func.deprecated, func.since = parse_func_desc(state, element)
- # Friend functions have friend as type. That's just awful. COME ON.
- if func.type.startswith('friend '):
- func.type = func.type[7:]
-
def is_identifier(a): return a == '_' or a.isalnum()
# Extract function signature to prefix, suffix and various flags. Important
# things affecting caller such as static or const (and rvalue overloads)
# are put into signature prefix/suffix, other things to various is_*
# properties.
- if func.type == 'constexpr': # Constructors
- func.type = ''
- func.is_constexpr = True
- elif func.type.startswith('constexpr'):
- func.type = func.type[10:]
- func.is_constexpr = True
- # For some effing reason, when a constexpr function has decltype(auto)
- # return type, Doxygen swaps the order of those two, causing the constexpr
- # to be last. See the cpp_function_attributes test for a verification.
- elif func.type.endswith('constexpr'):
- func.type = func.type[:-10]
- func.is_constexpr = True
- else:
- func.is_constexpr = False
- # When 1.8.18 encounters `constexpr static`, it keeps the static there. For
- # `static constexpr` it doesn't. In both cases the static="yes" is put
- # there correctly. WHY DOXYGEN, WHY?!
- if func.type.startswith('static'):
- func.type = func.type[7:]
+ #
+ # First the prefix keywords - Doxygen has a habit of leaking attributes and
+ # other specifiers into the function's return type, and not necessarily
+ # in any consistent order (including swapping it with the actual type!)
+ #
+ # (Note that since 1.8.16 the keyword/type ordering has not been a problem,
+ # but this handling is left as a future-proofing mechanism.)
+ exposed_attribute_keywords = [
+ 'constexpr',
+ 'consteval',
+ 'explicit',
+ 'virtual'
+ ]
+ ignored_attribute_keywords = [
+ 'static', # Included in func.prefix already
+ 'friend',
+ 'inline'
+ ]
+ for kw in exposed_attribute_keywords:
+ setattr(func, 'is_' + kw, False)
+ is_static = False
+ matched_bad_keyword = True
+ while matched_bad_keyword:
+ matched_bad_keyword = False
+ for kw in exposed_attribute_keywords + ignored_attribute_keywords:
+ if func.type == kw: # constructors
+ func.type = ''
+ elif func.type.startswith(kw + ' '):
+ func.type = func.type[len(kw):].strip()
+ elif func.type.endswith(' ' + kw):
+ func.type = func.type[:len(kw)].strip()
+ else:
+ continue
+ matched_bad_keyword = True
+ if kw in exposed_attribute_keywords:
+ setattr(func, 'is_' + kw, True)
+ elif kw == 'static':
+ is_static = True
+ # Merge any leaked attributes with their corresponding XML attributes to
+ # account for the situation where Doxygen has only half got it right
+ # (which, honestly, is most of the time)
+ func.is_explicit = func.is_explicit or element.attrib['explicit'] == 'yes'
+ func.is_virtual = func.is_virtual or element.attrib['virt'] != 'non-virtual'
+ is_static = is_static or element.attrib['static'] == 'yes'
+ if 'constexpr' in element.attrib:
+ func.is_constexpr = func.is_constexpr or element.attrib['constexpr'] == 'yes'
+ if 'consteval' in element.attrib:
+ func.is_consteval = func.is_consteval or element.attrib['consteval'] == 'yes'
func.prefix = ''
- func.is_explicit = element.attrib['explicit'] == 'yes'
- func.is_virtual = element.attrib['virt'] != 'non-virtual'
- if element.attrib['static'] == 'yes':
+ if is_static:
func.prefix += 'static '
# Extract additional C++11 stuff from the signature. Order matters, going
# from the keywords that can be rightmost to the leftmost.
</div>
{% endif %}
{% set j = joiner(',\n ') %}
- <span class="m-doc-wrap-bumper">{{ func.prefix }}{{ func.type }} {{ prefix }}</span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#{{ func.id }}" class="m-doc-self">{{ func.name }}</a>(</span><span class="m-doc-wrap">{% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.is_explicit %} <span class="m-label m-info">explicit</span> {% endif %}{% if func.is_final %} <span class="m-label m-warning">final</span>{% elif func.is_override %} <span class="m-label m-warning">override</span>{% elif func.is_pure_virtual %} <span class="m-label m-warning">pure virtual</span>{% elif func.is_virtual %} <span class="m-label m-warning">virtual</span>{% endif %}{% if func.is_protected %} <span class="m-label m-warning">protected{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_private %} <span class="m-label m-danger">private{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_signal %} <span class="m-label m-success">signal</span>{% elif func.is_slot %} <span class="m-label m-success">public slot</span>{% endif %}{% if func.is_defaulted %} <span class="m-label m-info">defaulted</span>{% endif %}{% if func.is_deleted %} <span class="m-label m-danger">deleted</span>{% endif %}{% if func.is_constexpr %} <span class="m-label m-primary">constexpr</span>{% endif %}{% if func.is_conditional_noexcept %} <span class="m-label m-success">noexcept(…)</span>{% elif func.is_noexcept %} <span class="m-label m-success">noexcept</span>{% endif %}{% if func.since %} {{ func.since }}{% endif %}</span></span>
+ <span class="m-doc-wrap-bumper">{{ func.prefix }}{{ func.type }} {{ prefix }}</span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#{{ func.id }}" class="m-doc-self">{{ func.name }}</a>(</span><span class="m-doc-wrap">{% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.is_explicit %} <span class="m-label m-info">explicit</span> {% endif %}{% if func.is_final %} <span class="m-label m-warning">final</span>{% elif func.is_override %} <span class="m-label m-warning">override</span>{% elif func.is_pure_virtual %} <span class="m-label m-warning">pure virtual</span>{% elif func.is_virtual %} <span class="m-label m-warning">virtual</span>{% endif %}{% if func.is_protected %} <span class="m-label m-warning">protected{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_private %} <span class="m-label m-danger">private{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_signal %} <span class="m-label m-success">signal</span>{% elif func.is_slot %} <span class="m-label m-success">public slot</span>{% endif %}{% if func.is_defaulted %} <span class="m-label m-info">defaulted</span>{% endif %}{% if func.is_deleted %} <span class="m-label m-danger">deleted</span>{% endif %}{% if func.is_consteval %} <span class="m-label m-primary">consteval</span>{% elif func.is_constexpr %} <span class="m-label m-primary">constexpr</span>{% endif %}{% if func.is_conditional_noexcept %} <span class="m-label m-success">noexcept(…)</span>{% elif func.is_noexcept %} <span class="m-label m-success">noexcept</span>{% endif %}{% if func.since %} {{ func.since }}{% endif %}</span></span>
{% if func.include and compound.templates == None and func.templates == None %}
<div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="{{ func.include[1] }}">{{ func.include[0] }}</a></div>
{% endif %}
<div class="m-doc-template">template<{% for t in func.templates %}{{ j() }}{{ t.type }}{% if t.name %} {{ t.name }}{% endif %}{% if t.default %} = {{ t.default }}{% endif %}{% endfor %}></div>
{% endif %}
{% set j = joiner(',\n ') %}
- <span class="m-doc-wrap-bumper">{{ func.prefix }}{% if func.type == 'void' %}void {% elif func.type %}auto {% endif %}<a href="{% if func.base_url != compound.url %}{{ func.base_url }}{% endif %}#{{ func.id }}" class="m-doc{% if not func.has_details and func.base_url == compound.url %}-self{% endif %}">{{ func.name }}</a>(</span><span class="m-doc-wrap">{% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.type and func.type != 'void' %} -> {{ func.type }}{% endif %}{% if func.deprecated %} <span class="m-label m-danger">{{ func.deprecated }}</span>{% endif %}{% if not func.type or mark_nonpublic %}{% if func.is_protected %} <span class="m-label m-flat m-warning">protected{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_private %} <span class="m-label m-flat m-danger">private{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_signal %} <span class="m-label m-flat m-success">signal</span>{% elif func.is_slot %} <span class="m-label m-flat m-success">public slot</span>{% endif %}{% endif %}{% if func.is_defaulted %} <span class="m-label m-flat m-info">defaulted</span>{% endif %}{% if func.is_deleted %} <span class="m-label m-flat m-danger">deleted</span>{% endif %}{% if func.is_explicit %} <span class="m-label m-flat m-info">explicit</span> {% endif %}{% if func.is_final %} <span class="m-label m-flat m-warning">final</span>{% elif func.is_override %} <span class="m-label m-flat m-warning">override</span>{% elif func.is_pure_virtual %} <span class="m-label m-flat m-warning">pure virtual</span>{% elif func.is_virtual %} <span class="m-label m-flat m-warning">virtual</span>{% endif %}{% if func.is_constexpr %} <span class="m-label m-flat m-primary">constexpr</span>{% endif %}{% if func.is_conditional_noexcept %} <span class="m-label m-flat m-success">noexcept(…)</span>{% elif func.is_noexcept %} <span class="m-label m-flat m-success">noexcept</span>{% endif %}{% if func.since %} {{ func.since }}{% endif %}</span>
+ <span class="m-doc-wrap-bumper">{{ func.prefix }}{% if func.type == 'void' %}void {% elif func.type %}auto {% endif %}<a href="{% if func.base_url != compound.url %}{{ func.base_url }}{% endif %}#{{ func.id }}" class="m-doc{% if not func.has_details and func.base_url == compound.url %}-self{% endif %}">{{ func.name }}</a>(</span><span class="m-doc-wrap">{% for param in func.params %}{{ j() }}{{ param.type_name }}{% if param.default %} = {{ param.default }}{% endif %}{% endfor %}){{ func.suffix }}{% if func.type and func.type != 'void' %} -> {{ func.type }}{% endif %}{% if func.deprecated %} <span class="m-label m-danger">{{ func.deprecated }}</span>{% endif %}{% if not func.type or mark_nonpublic %}{% if func.is_protected %} <span class="m-label m-flat m-warning">protected{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_private %} <span class="m-label m-flat m-danger">private{% if func.is_slot %} slot{% endif %}</span>{% elif func.is_signal %} <span class="m-label m-flat m-success">signal</span>{% elif func.is_slot %} <span class="m-label m-flat m-success">public slot</span>{% endif %}{% endif %}{% if func.is_defaulted %} <span class="m-label m-flat m-info">defaulted</span>{% endif %}{% if func.is_deleted %} <span class="m-label m-flat m-danger">deleted</span>{% endif %}{% if func.is_explicit %} <span class="m-label m-flat m-info">explicit</span> {% endif %}{% if func.is_final %} <span class="m-label m-flat m-warning">final</span>{% elif func.is_override %} <span class="m-label m-flat m-warning">override</span>{% elif func.is_pure_virtual %} <span class="m-label m-flat m-warning">pure virtual</span>{% elif func.is_virtual %} <span class="m-label m-flat m-warning">virtual</span>{% endif %}{% if func.is_consteval %} <span class="m-label m-flat m-primary">consteval</span>{% elif func.is_constexpr %} <span class="m-label m-flat m-primary">constexpr</span>{% endif %}{% if func.is_conditional_noexcept %} <span class="m-label m-flat m-success">noexcept(…)</span>{% elif func.is_noexcept %} <span class="m-label m-flat m-success">noexcept</span>{% endif %}{% if func.since %} {{ func.since }}{% endif %}</span>
</dt>
<dd>{{ func.brief }}</dd>
/** @brief A friend function */
friend void friendFunction(int a, void* b);
+ /** @brief A 'hidden friend' operator */
+ friend bool operator==(const Class&, const Class&) noexcept;
+
+ /** @brief A constexpr 'hidden friend' operator */
+ friend constexpr bool operator!=(const Class&, const Class&) noexcept;
+
/** @{ @name Group with friend functions */
/** @brief A friend grouped function */
void* b)</span>
</dt>
<dd>A friend function.</dd>
+ <dt id="a065fe9c7fbe768fdb374fd1970a83576">
+ <span class="m-doc-wrap-bumper">auto <a href="#a065fe9c7fbe768fdb374fd1970a83576" class="m-doc-self">operator==</a>(</span><span class="m-doc-wrap">const <a href="classClass.html" class="m-doc">Class</a>&,
+ const <a href="classClass.html" class="m-doc">Class</a>&) -> bool <span class="m-label m-flat m-success">noexcept</span></span>
+ </dt>
+ <dd>A 'hidden friend' operator.</dd>
+ <dt id="ae506b77d3dfd4c00550bb3c4e2394e22">
+ <span class="m-doc-wrap-bumper">auto <a href="#ae506b77d3dfd4c00550bb3c4e2394e22" class="m-doc-self">operator!=</a>(</span><span class="m-doc-wrap">const <a href="classClass.html" class="m-doc">Class</a>&,
+ const <a href="classClass.html" class="m-doc">Class</a>&) -> bool <span class="m-label m-flat m-primary">constexpr</span> <span class="m-label m-flat m-success">noexcept</span></span>
+ </dt>
+ <dd>A constexpr 'hidden friend' operator.</dd>
</dl>
</section>
</div>
*/
constexpr static int constexprStaticFunction();
+ /**
+ * @brief Consteval before static
+ *
+ * Same as above, but for C++20's consteval.
+ */
+ consteval static int constevalStaticFunction();
+
/**
* @brief Constexpr after static
*
*/
static constexpr int staticConstexprFunction();
+ /**
+ * @brief Consteval after static
+ *
+ * Same as above, but for C++20's consteval.
+ */
+ static consteval int staticConstevalFunction();
+
/**
* @brief Combined default and noexcept
*
<span class="m-doc-wrap-bumper">static auto <a href="#a77f46786436a39eb3b53343580f41b89" class="m-doc">constexprStaticFunction</a>(</span><span class="m-doc-wrap">) -> int <span class="m-label m-flat m-primary">constexpr</span></span>
</dt>
<dd>Constexpr before static.</dd>
+ <dt>
+ <span class="m-doc-wrap-bumper">static auto <a href="#a37fb9b85cc5a56110f12460a822112a9" class="m-doc">constevalStaticFunction</a>(</span><span class="m-doc-wrap">) -> int <span class="m-label m-flat m-primary">consteval</span></span>
+ </dt>
+ <dd>Consteval before static.</dd>
<dt>
<span class="m-doc-wrap-bumper">static auto <a href="#a178c5f6f19fa2ffb1fc7a346e2e877d9" class="m-doc">staticConstexprFunction</a>(</span><span class="m-doc-wrap">) -> int <span class="m-label m-flat m-primary">constexpr</span></span>
</dt>
<dd>Constexpr after static.</dd>
+ <dt>
+ <span class="m-doc-wrap-bumper">static auto <a href="#a26b977ac73c54993504324aae7a08e08" class="m-doc">staticConstevalFunction</a>(</span><span class="m-doc-wrap">) -> int <span class="m-label m-flat m-primary">consteval</span></span>
+ </dt>
+ <dd>Consteval after static.</dd>
</dl>
</section>
<section id="typeless-methods">
</h3>
<p>Constexpr before static.</p>
<p>1.8.18 puts both <code>constexpr</code> and <code>static</code> into the return type so I have to remove them. WHY! HOW IS THAT USEFUL IN ANY WAY?!</p>
+ </div></section>
+ <section class="m-doc-details" id="a37fb9b85cc5a56110f12460a822112a9"><div>
+ <h3>
+ <span class="m-doc-wrap-bumper">static int Foo::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#a37fb9b85cc5a56110f12460a822112a9" class="m-doc-self">constevalStaticFunction</a>(</span><span class="m-doc-wrap">) <span class="m-label m-primary">consteval</span></span></span>
+ </h3>
+ <p>Consteval before static.</p>
+<p>Same as above, but for C++20's consteval.</p>
</div></section>
<section class="m-doc-details" id="a178c5f6f19fa2ffb1fc7a346e2e877d9"><div>
<h3>
</h3>
<p>Constexpr after static.</p>
<p>In this case, <code>static</code> is not in the return type. FFS.</p>
+ </div></section>
+ <section class="m-doc-details" id="a26b977ac73c54993504324aae7a08e08"><div>
+ <h3>
+ <span class="m-doc-wrap-bumper">static int Foo::<wbr /></span><span class="m-doc-wrap"><span class="m-doc-wrap-bumper"><a href="#a26b977ac73c54993504324aae7a08e08" class="m-doc-self">staticConstevalFunction</a>(</span><span class="m-doc-wrap">) <span class="m-label m-primary">consteval</span></span></span>
+ </h3>
+ <p>Consteval after static.</p>
+<p>Same as above, but for C++20's consteval.</p>
</div></section>
<section class="m-doc-details" id="ad5953d17211071264b501747c67e6fdc"><div>
<h3>