Sometime ago there were some proposals to allow User Defined Attributes as consteval or constexpr, but among other concerns, it conflicted with "attributes should not affect the program" and standard attributes are not "typed", and also not being part of the type of wherever they are attached. About that, we could change that to

1 - Apply "attributes should not affect the program" only on standard attributes the statement will become "standard attributes should not affect the program"
2 - Allow consteval UDA´s to be typed, and "affect" the program, I mean, by being constructed in compile time and anything derived from that, subjected to "normal" strong typed compile time behavior.
3 - Not be part of whatever type/template/declaration that it is being attached to.

      In this spirit I had some thoughts about the subject taking this path, and giving my 2 cents ( mostly in template cases ) :
 
1 - It would be useful to reflect a single instance of attribute "my_attr1" for all instances of X and a different instance of the attribute " my_attr2" for each X instantiation.

[[ my_attr1{} ]] template<typename T> [[  my_attr2<T>{} ]] struct X {};
X<int>    x_int ;
X<float>  x_float;

so, if we ask for "attributes_of( type_of(^x_int) )", it should be expanded as

constexpr auto temp1 =  my_attr1{};
constexpr auto temp2 =  my_attr2<int>{}
attributes_of( type_of(^x_int) ) == { ^temp1, ^temp2 };

constexpr auto temp3 =  my_attr2<float>()
attributes_of( type_of(^x_float) ) == { ^temp1, ^temp3 };

instead of

attributes_of( type_of(^x_int) )   == { my_attr1{} my_attr2<int>{} };
attributes_of( type_of(^x_float) ) == { my_attr1{} my_attr2< float >{} };

so, subsequent calls to attributes_of( type_of(^x_int) ) would not construct other instances of  my_attr1 / my_attr2 , right ?

2 - What if my_attr3 does not depend on T ?. Well the same, one my_attr3 to each instance 

[[  my_attr1{} ]] template<typename T> [[  my_attr3{ constexpr_foo_counter() } ]] struct X {};
X<int>  x_int  ;
X<float>  x_float;

constexpr auto temp1 = my_attr1{};
constexpr auto temp2 = my_attr3{ constexpr_foo_counter()  }
attributes_of( type_of(^x_int) ) == { ^temp1, ^temp2 };

constexpr auto temp3 =  my_attr3constexpr_foo_counter()  };   // calling again possibly with different result
attributes_of( type_of(^x_float) ) == { ^temp1, ^temp3 };

3 - Would it be possible to get the instance of my_attr1, without instantiation of X, also be possible to get the template name "my_attr2" without instantiating X, just reflecting the template ( not a particular instance )

[[  my_attr1{} ]] template<typename T> [[  my_attr2<T>{} ]] struct X {};

constexpr auto temp1 =  my_attr1{};
attributes_of( ^X ) == { ^temp1, ^my_attr2 };

4 - Specializations should forget all previous attributes.

template<> [[   my_attr4{} ]] struct X<void> {} x_void;

constexpr auto temp1 =  my_attr4{};
attributes_of( type_of(^x_void ) ) == { ^temp1  };

Since one can get the "parent" attributes from de template declaration

attributes_of( template_of( type_of(^x_void ) ) ) == attributes_of( ^X );

5 - All standard attributes must belong to a std:: namespace, avoiding conflict in future proposals.


Thanks

Em qua., 24 de abr. de 2024 às 08:30, Jean-Baptiste Vallon Hoarau via SG7 <sg7@lists.isocpp.org> escreveu:
What Barry was saying is that this cannot work : templates are instantiated per type, and the attributes are not part of the type, so the information is simply not passed down to the instantiation of the template, reflection or not. 

Le mer. 24 avr. 2024 à 13:26, Aurelien Cassagnes via SG7 <sg7@lists.isocpp.org> a écrit :
Barry I understand that right now there is no reasons for it to work, the purpose of this thread is to flesh out what the proposal look like. 
Gather interest and feedback not share an hypothetical  implementation because it doesnt exist yet. 

Besides seeing interest, the feedback i’m interested is what sections need to be discussed in more detail in the draft for it to become more meaningful
thanks. 

Sent from Gmail Mobile


On Sun, Apr 21, 2024 at 1:47 Barry Revzin <barry.revzin@gmail.com> wrote:


On Fri, Apr 19, 2024, 9:53 PM Aurelien Cassagnes via SG7 <sg7@lists.isocpp.org> wrote:
Fleshed out the proposal draft and it's available for feedback at https://github.com/zebullax/wg21/blob/main/generated/proposal.pdf

How do you expect this to work exactly?

The type of foo is bool(int),  it's not [[nodiscard]] bool(int). Regardless of the question of reflecting on attributes... logInvoke(foo, 0) is going to call logInvoke<bool(int), int>. There aren't any attributes left to reflect on anymore.

Barry
--
SG7 mailing list
SG7@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/sg7
--
SG7 mailing list
SG7@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/sg7