Date: Fri, 06 Mar 2026 10:53:27 +0000
On Friday, March 6th, 2026 at 4:07 AM, Keenan Horrigan via Std-Discussion <std-discussion_at_[hidden]> wrote:
> Hello,
>
> I was wondering what the proper behavior of the following code should be:
>
> #include <meta>
>
> [[=1]]
> void function();
>
> static_assert(annotations_of(^^function).size() == 1);
>
> template<auto Value>
> consteval void annotate_function() {
> [[=Value]]
> void function();
> }
>
> consteval {
> annotate_function<2>();
> }
>
> int main() {
> static constexpr auto NumAnnotations = annotations_of(^^function).size();
>
> std::printf("Annotation count: %zu", NumAnnotations);
> }
>
> Godbolt link: https://godbolt.org/z/4dca5xEPe
>
> With GCC trunk, it prints "Annotation count: 1", but with the experimental Clang reflection branch it prints "Annotation count: 3". I assume Clang here is acting erroneously in some regard because it appears to be duplicating the initial annotation placed on the function. But what I'm more interested in is whether the compiler should be appending the annotation from annotate_function globally.
>
> As well, if one removes the templating from annotate_function, GCC continues to report only one annotation, but Clang reports two: https://godbolt.org/z/74evKWT3a
>
> I'd also be interested in how that is meant to behave.
>
To add to that, has_identifier() and (supposedly) has_default_argument()
are also influenced by block-scope declarations. In case of
has_identifer() it's explicitly given as an example
<https://eel.is/c++draft/meta.reflection#names-example-1>.
Default function arguments in block-scope declarations are limited to
that scope, which can create funny situations:
#include <meta>
int f(int);
constexpr auto p = parameters_of(^^f)[0];
static_assert(not has_default_argument(p));
void g() {
int f(int = 0);
}
static_assert(has_default_argument(p));
int x = f(); // error
https://godbolt.org/z/Ghc3cn8Gn
This might affect named arguments too (which I hope we'll get
eventually) depending on how they're specified. It's also yet another
avenue for stateful metaprogramming.
> Hello,
>
> I was wondering what the proper behavior of the following code should be:
>
> #include <meta>
>
> [[=1]]
> void function();
>
> static_assert(annotations_of(^^function).size() == 1);
>
> template<auto Value>
> consteval void annotate_function() {
> [[=Value]]
> void function();
> }
>
> consteval {
> annotate_function<2>();
> }
>
> int main() {
> static constexpr auto NumAnnotations = annotations_of(^^function).size();
>
> std::printf("Annotation count: %zu", NumAnnotations);
> }
>
> Godbolt link: https://godbolt.org/z/4dca5xEPe
>
> With GCC trunk, it prints "Annotation count: 1", but with the experimental Clang reflection branch it prints "Annotation count: 3". I assume Clang here is acting erroneously in some regard because it appears to be duplicating the initial annotation placed on the function. But what I'm more interested in is whether the compiler should be appending the annotation from annotate_function globally.
>
> As well, if one removes the templating from annotate_function, GCC continues to report only one annotation, but Clang reports two: https://godbolt.org/z/74evKWT3a
>
> I'd also be interested in how that is meant to behave.
>
To add to that, has_identifier() and (supposedly) has_default_argument()
are also influenced by block-scope declarations. In case of
has_identifer() it's explicitly given as an example
<https://eel.is/c++draft/meta.reflection#names-example-1>.
Default function arguments in block-scope declarations are limited to
that scope, which can create funny situations:
#include <meta>
int f(int);
constexpr auto p = parameters_of(^^f)[0];
static_assert(not has_default_argument(p));
void g() {
int f(int = 0);
}
static_assert(has_default_argument(p));
int x = f(); // error
https://godbolt.org/z/Ghc3cn8Gn
This might affect named arguments too (which I hope we'll get
eventually) depending on how they're specified. It's also yet another
avenue for stateful metaprogramming.
Received on 2026-03-06 10:53:35
