Date: Mon, 28 Nov 2022 11:50:03 -0600
Yeah, I knew it would be scary, but I braved it anyway because this has
been a recurring pain point for me and has often made me reach for less
satisfying alternatives or ones with other draw-backs that I'm not willing
to incur (macros limit the design/readability in other ways, among other
problems).
This is probably my bad, but I should've probably made it clear that the
attribute would apply only to the parameter list for the template
class/function it was applied to. So "f" in the example you gave would be
just fine and isn't affected by the attribute. Only the template parameter
list for "ABC::Color" would be affected, or at least that was the
intention. And it could be a rule that only the primary template can have
this attribute so as to not fall into the trap of having conflicting
attributes on different specializations.
I'm not sure what problem your last example is trying to demonstrate
though. I'm not sure if there is supposed to be an implied attribute on S?
I definitely wouldn't want enumeration values to be automatically
deduced without explicit say-so, which is why I proposed the "context"
attribute.
Regardless, the point that Peter brought up about ignorable attributes
(nice article on that, by the way!) is a good one and alone makes this a
less than solid proposal barring some alternative syntax.
Thanks for the input,
Ryan Klaus
On Mon, Nov 28, 2022 at 11:09 AM Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
wrote:
> On Mon, Nov 28, 2022 at 11:58 AM Ryan Klaus via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>>
>> Correct me if I'm wrong, but don't the current disambiguation rules for
>> using statements cover this?
>> These conflicts could occur with using statements already allowed in the
>> language.
>> Here's an example:
>>
>> enum class ColorComponents {
>> RGBA = 7
>> };
>>
>> enum class ColorComponents2 {
>> RGBA = 42
>> };
>>
>> struct RGBA {};
>> int main () {
>> using enum ColorComponents;
>> //using enum ColorComponents2;
>> // ^ compilation error
>>
>> //static constexpr ColorComponents RGBA = ColorComponents(42);
>> // ^ compilation error
>>
>> struct RGBA x; // Removing "struct" makes this ambiguous
>> auto y = (struct RGBA){}; // Removing "struct" makes this ambiguous
>> ColorComponents z = RGBA; // Okay
>>
>> return (int)RGBA + (int)z;
>> }
>>
>>
>> Attempting to use two enums that have the same enumerator name results in
>> a compile error, and theoretically my proposal would work in the same
>> fashion as this makes no sense. Similarly, types can either be
>> disambiguated through a variety of means or, when not properly
>> disambiguated, throw a compile error. Again, theoretically my proposal
>> would work in this way.
>>
>
> Perhaps, but you'd have to actually come up with the rules that make it
> work "that way."
> I infer that you're thinking of a rule something like "For each non-type
> template parameter of enumeration type, look up all names within the
> template argument as if they were in a scope preceded by `using enum
> *the-enum-type*`." But then you still have problems with overloaded
> templates, where you *don't know* whether a given parameter is of
> enumeration type or not:
>
> template<ColorComponentLayout, ColorComponents> void f(); // #1
> enum NumberOfBalloons { _99, _8888, _777777 };
> template<ColorComponentLayout, NumberOfBalloons> void f(); // #2
> int main() {
> f<RGBA, _8888>(); // Ambiguous? or unambiguously a call to f #2
> with NumberOfBalloons::_8888?
> }
>
> And you have new problems — or at least possibilities-for-confusion
> ("veridical paradoxes") — with things like:
>
> enum class E { A,B,C,D,E,F,G };
> template<E> struct S {};
> S<A> s; // proposed OK, means S<E::A>
> S<(E)-A> s; // proposed OK, means S<(E::E)-E::A>, *not* S<(E)-E::A>
> i.e. S<E(0)>
>
> Modifying the name lookup rules is one of the scariest things you can do
> in C++-proposal-land.
>
> –Arthur
>
been a recurring pain point for me and has often made me reach for less
satisfying alternatives or ones with other draw-backs that I'm not willing
to incur (macros limit the design/readability in other ways, among other
problems).
This is probably my bad, but I should've probably made it clear that the
attribute would apply only to the parameter list for the template
class/function it was applied to. So "f" in the example you gave would be
just fine and isn't affected by the attribute. Only the template parameter
list for "ABC::Color" would be affected, or at least that was the
intention. And it could be a rule that only the primary template can have
this attribute so as to not fall into the trap of having conflicting
attributes on different specializations.
I'm not sure what problem your last example is trying to demonstrate
though. I'm not sure if there is supposed to be an implied attribute on S?
I definitely wouldn't want enumeration values to be automatically
deduced without explicit say-so, which is why I proposed the "context"
attribute.
Regardless, the point that Peter brought up about ignorable attributes
(nice article on that, by the way!) is a good one and alone makes this a
less than solid proposal barring some alternative syntax.
Thanks for the input,
Ryan Klaus
On Mon, Nov 28, 2022 at 11:09 AM Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
wrote:
> On Mon, Nov 28, 2022 at 11:58 AM Ryan Klaus via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>>
>> Correct me if I'm wrong, but don't the current disambiguation rules for
>> using statements cover this?
>> These conflicts could occur with using statements already allowed in the
>> language.
>> Here's an example:
>>
>> enum class ColorComponents {
>> RGBA = 7
>> };
>>
>> enum class ColorComponents2 {
>> RGBA = 42
>> };
>>
>> struct RGBA {};
>> int main () {
>> using enum ColorComponents;
>> //using enum ColorComponents2;
>> // ^ compilation error
>>
>> //static constexpr ColorComponents RGBA = ColorComponents(42);
>> // ^ compilation error
>>
>> struct RGBA x; // Removing "struct" makes this ambiguous
>> auto y = (struct RGBA){}; // Removing "struct" makes this ambiguous
>> ColorComponents z = RGBA; // Okay
>>
>> return (int)RGBA + (int)z;
>> }
>>
>>
>> Attempting to use two enums that have the same enumerator name results in
>> a compile error, and theoretically my proposal would work in the same
>> fashion as this makes no sense. Similarly, types can either be
>> disambiguated through a variety of means or, when not properly
>> disambiguated, throw a compile error. Again, theoretically my proposal
>> would work in this way.
>>
>
> Perhaps, but you'd have to actually come up with the rules that make it
> work "that way."
> I infer that you're thinking of a rule something like "For each non-type
> template parameter of enumeration type, look up all names within the
> template argument as if they were in a scope preceded by `using enum
> *the-enum-type*`." But then you still have problems with overloaded
> templates, where you *don't know* whether a given parameter is of
> enumeration type or not:
>
> template<ColorComponentLayout, ColorComponents> void f(); // #1
> enum NumberOfBalloons { _99, _8888, _777777 };
> template<ColorComponentLayout, NumberOfBalloons> void f(); // #2
> int main() {
> f<RGBA, _8888>(); // Ambiguous? or unambiguously a call to f #2
> with NumberOfBalloons::_8888?
> }
>
> And you have new problems — or at least possibilities-for-confusion
> ("veridical paradoxes") — with things like:
>
> enum class E { A,B,C,D,E,F,G };
> template<E> struct S {};
> S<A> s; // proposed OK, means S<E::A>
> S<(E)-A> s; // proposed OK, means S<(E::E)-E::A>, *not* S<(E)-E::A>
> i.e. S<E(0)>
>
> Modifying the name lookup rules is one of the scariest things you can do
> in C++-proposal-land.
>
> –Arthur
>
Received on 2022-11-28 17:50:15