1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
#include <type_traits>
/** @brief Pathological cases of function attributes */
struct Foo {
/**
* @brief Constexpr before static
*
* 1.8.18 puts both `constexpr` and `static` into the return type so I have
* to remove them. WHY! HOW IS THAT USEFUL IN ANY WAY?!
*/
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
*
* In this case, `static` is not in the return type. FFS.
*/
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
*
* Details.
*/
Foo(Foo&&) noexcept = default;
/**
* @brief Conditional noexcept
*
* Details.
*/
Foo(const Foo&) noexcept(std::is_nothrow_copy_constructible<Foo>::value);
/**
* @brief Combined conditional noexcept and delete
*
* Details.
*/
Foo& operator=(const Foo&) noexcept(std::is_nothrow_copy_constructible<Foo>::value) = delete;
/**
* @brief Const, conditional noexcept and a pure virtual
*
* Details.
*/
virtual void foo() const noexcept(false) = 0;
/**
* @brief Random type and constexpr together
*
* This is okay.
*/
constexpr Foo& bar() noexcept;
/**
* @brief decltype(auto) and constexpr together
*
* For some reason, due to decltype(auto), Doxygen swaps the order, causing
* the constexpr to be hard to detect. Don't even ask how it handles
* trailing return types. It's just HORRIBLE.
*/
constexpr decltype(auto) baz() noexcept;
};
/** @brief Base class */
class Base {
public:
/** @brief Do a thing with crazy attribs */
virtual void doThing() const noexcept(false);
private:
/** @brief Do another thing, privately */
virtual void doAnotherThing();
/**
* @brief Do yet another thing, privately
*
* The override will get hidden because `INHERIT_DOCS` is disabled.
*/
virtual void doYetAnotherThing();
/* Not documented, should be hidden */
virtual void doUndocumentedThing();
};
/** @brief A derived class */
class Derived: public Base {
protected:
/** @brief Do a thing, overridden, now protected */
void doThing() const noexcept(false) override;
private:
/**
* @brief Do another thing, privately, with different docs
*
* Documented, so not hidden.
*/
void doAnotherThing() override;
/* Hidden because there's no doc block */
void doYetAnotherThing() override;
/* Hidden as well because even the parent was undocumented */
void doUndocumentedThing() override;
};
/** @brief Various uses of final keywords */
struct Final final: protected Base {
/**
* @brief Final w/o override (will cause a compiler warning)
*
* Details.
*/
void doThing() const noexcept(false) final;
/**
* @brief Final override
*
* Details.
*/
void doAnotherThing() final override;
/**
* @brief Override final
*
* Details.
*/
void doYetAnotherThing() override final;
};
|