Date: Fri, 28 Jan 2022 09:30:02 -0500

> On Jan 28, 2022, at 7:22 AM, Cleiton Santoia via SG7 <sg7_at_[hidden]> wrote:

>

> If the template instantiation depends on an incomplete type, will two consecutive calls use the same template instantiation even if the type changed ?

>

> template<typename T>

> struct has_members_with_an_a {

> constexpr static int value = /* some wizardry to get number of members of T with an 'a' in the name*/ ; (1)

> };

>

> struct X {

> int a;

> constexpr static int sz = refl< X >::value; // sz == 1; (2)

> int another; // adding some new

> constexpr static int sz2 = refl< X >::value; // sz still == 1 (3)

> };

Assuming that the “wizardry” can look into classes in the process of being defined, I believe that’s an ODR violation: Your two points of instantiation (for refl<X>::value) are not equivalent (unless your “wizardry” guards against that, e.g. by testing “is_incomplete” first). See [temp.point]/7.

(FWIW, the current intent in P1240 is that, e.g., members_of(^T) would indeed give you a partial set of member while T is being defined. That’s not explicitly stated in the paper, however, and we could change that if we think it's overall beneficial, though I suspect it’s not.)

>

> Q1.) Does the template has_members_with_an_a "freezes" between calls, since X will lead to the same Type ? In (3) we already have a "has_members_with_an_a<X>" instantiated ?

>

> Q2.) It also happens if we change (2) and (3) to call using ^X instead of X ?

Yes, that is also likely to result in an ODR violation.

>

> template<auto RT>

> struct has_members_with_an_a {

> constexpr static bool value = /* some wizardry to get the number of members of RT with an 'a' in the name*/ ;

> };

>

> struct X {

> int a;

> constexpr static int sz = refl< ^X >::value; // sz == 1; (4)

> int another; // adding some new

> constexpr static int sz2 = refl< ^X >::value; // sz still == 1 (5)

> };

>

> Because we already have an instance of has_members_with_an_a<^X> with the same "underlying int-ish value of ^X" ?

>

> Q3.) Even if we change (1) to use consteval, still (2) == (3) ?

Yes. This is not a matter of “how” values are computed, but just a consequence of producing different results at different instantiation points.

Daveed

>

> template<auto RT>

> struct has_members_with_an_a {

> consteval int value() { /* some wizardry to get the members of members of RT with an 'a' in the name*/ ; (6) }

> };

>

>

> Cleiton

> --

> SG7 mailing list

> SG7_at_[hidden]

> https://lists.isocpp.org/mailman/listinfo.cgi/sg7

>

> If the template instantiation depends on an incomplete type, will two consecutive calls use the same template instantiation even if the type changed ?

>

> template<typename T>

> struct has_members_with_an_a {

> constexpr static int value = /* some wizardry to get number of members of T with an 'a' in the name*/ ; (1)

> };

>

> struct X {

> int a;

> constexpr static int sz = refl< X >::value; // sz == 1; (2)

> int another; // adding some new

> constexpr static int sz2 = refl< X >::value; // sz still == 1 (3)

> };

Assuming that the “wizardry” can look into classes in the process of being defined, I believe that’s an ODR violation: Your two points of instantiation (for refl<X>::value) are not equivalent (unless your “wizardry” guards against that, e.g. by testing “is_incomplete” first). See [temp.point]/7.

(FWIW, the current intent in P1240 is that, e.g., members_of(^T) would indeed give you a partial set of member while T is being defined. That’s not explicitly stated in the paper, however, and we could change that if we think it's overall beneficial, though I suspect it’s not.)

>

> Q1.) Does the template has_members_with_an_a "freezes" between calls, since X will lead to the same Type ? In (3) we already have a "has_members_with_an_a<X>" instantiated ?

>

> Q2.) It also happens if we change (2) and (3) to call using ^X instead of X ?

Yes, that is also likely to result in an ODR violation.

>

> template<auto RT>

> struct has_members_with_an_a {

> constexpr static bool value = /* some wizardry to get the number of members of RT with an 'a' in the name*/ ;

> };

>

> struct X {

> int a;

> constexpr static int sz = refl< ^X >::value; // sz == 1; (4)

> int another; // adding some new

> constexpr static int sz2 = refl< ^X >::value; // sz still == 1 (5)

> };

>

> Because we already have an instance of has_members_with_an_a<^X> with the same "underlying int-ish value of ^X" ?

>

> Q3.) Even if we change (1) to use consteval, still (2) == (3) ?

Yes. This is not a matter of “how” values are computed, but just a consequence of producing different results at different instantiation points.

Daveed

>

> template<auto RT>

> struct has_members_with_an_a {

> consteval int value() { /* some wizardry to get the members of members of RT with an 'a' in the name*/ ; (6) }

> };

>

>

> Cleiton

> --

> SG7 mailing list

> SG7_at_[hidden]

> https://lists.isocpp.org/mailman/listinfo.cgi/sg7

Received on 2022-01-28 14:30:04