-
Notifications
You must be signed in to change notification settings - Fork 242
Not storing Annotation in menu item and segment improvement
#1112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
alabuzhev
merged 3 commits into
FarGroup:master
from
MKadaner:mzk/no-annotation-in-menu_item_ex
Jun 15, 2026
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| 6700 | ||
| 6701 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should have done it from the very beginning. I was not sure about availability of the concepts on all platforms. One can say I was lazy to do it right. Here are roughly my considerations.
Without this constraint,
segment_tcan be instantiated withdouble. With a few comparison operators sprinkled here and there, the behavior could be surprising. On the other hand, we do not need floating-point segments, so restricting is simpler and more natural than adding proper floating-point support.More immediately, I wanted to allow passing a "compatible" type to
start_or/end_or, not only exactT(because why not). However, there is nostd::nothrow_convertible_towhich would be required to guaranteenoexcept-ness of these functions. There are basically two options: definingnothrow_convertible_toor constraining the entire class to deal with integrals only (thenstd::convertible_to<T>combined withstd::integral Twill allow to safely promisenoexcept). Putting both considerations together, I decided to tighten the entire class.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, not exactly. One can imagine a non-trivial
operator int(). 🙁So, I'd say we need both, integral and
nothrow_convertible_to. Do you want me to fix it? If so, where should I define the concept? Is there a dedicated place?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm just not a big fan of overconstraining everything "just in case".
I've seen a compilation error somewhere recently, I don't remember the details, but essentially someone wanted to emulate __int128, not supported natively, naturally via a custom integer-like class, and it was used to instantiate some trivial algorithm elsewhere, but someone else decided to be overly meticulous and used this
integralconcept there, with somewhat predictable consequences.This usage of concepts undermines the core feature of templates - duck typing, and turns them into some C#-like generics where T must be known beforehand.
I'm not saying it's that important in this particular case (feel free to leave as is), I just don't like that this pattern sort of becomes the default in the industry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not agree, both in this case and in general.
With
segment, any integral type (and we enjoy 10 of them in C++) will work. The implementation does not assume any particular size or signedness, but it is about as much as we can support.segmentimplementation requires usual arithmetic and comparison operators onTand even slightly depends on integer overflow behavior (assert(length() >= 0);) so it cannot blindly accept just anything whichquacksadds and compares. Evendoublemay produce unexpected results and should be excluded. Thus, requiringstd::integral Tis not really over-constraining. It is requesting the minimum required to guarantee (without sending implementation complexity through the roof) the sane and expected behavior.As an aside, I like to say that "here we are not in the business of writing a general-purpose publicly available library," (compare to STL) so we do not need to go full-generic; our users (our beloved selves) will always be careful and won't do silly things. Nevertheless, when all we need is to drop in a one-word standard concept, we can afford it and get great benefit of extra type safety which eventually translates into overall software safety.
At the philosophical (or computer science) level, I think constrained C++ templates are still templates. Generally (unlike in this case), the (algorithm) implementation requires a type providing certain behavior (or combination of behaviors). If the type does not provide such and such functions or properties, ideally, the implementation does not compile and template SFINAE. That's fine, except for two things. First, sometimes it may accidentally compile with some obscure type, and Boom! Second, looking at the algorithm definition, one cannot easily say whether his shiny new
Int128will work with it.The
concepts andrequiresare the great way to document templates. Sometimes aconceptis just that, a concept. For example, many range-related concepts have associated semantic requirements (e.g.,std::ranges::sized_range). Such requirements are for documentation purposes only. They are not syntactically enforced. "The burden to ensure that library templates are instantiated with template arguments that satisfy these requirements is on the programmer."As long as a type faithfully behaves per the documented requirements (and supports necessary functions), it can be used in substitution. To me, it amounts to duck typing. The documentation helps avoiding possibly expensive mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's another place where concepts are too often misused.
SFINAE was a hack with a rather narrow application: emulating overload resolution in templates. That's literally in the name: it's not the end of the world if one substitution fails, another might succeed. And if none of them succeeds, you get a compilation error (great) with a rather horrible error message (not great, but better than nothing).
Now we got "concepts" built upon exactly the very same principles, and people started putting them into template signatures, effectively turning everything into SFINAE, even the templates that were never supposed to participate in overload resolution.
There is a rather noticeable difference between "the compiler found a matching template, attempted to instantiate it and failed to do so because this and that" and "the compiler found no candidates because all of them got rejected because <100 lines of instantiation stack for each of the candidates>. We can always improve the former with static_assert, but the latter is kinda unreadable by definition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some other compilers do a better job of it. I think that MSVC and clang's outputs for the concept-based variant are the cleanest. It is not a coincidence. One of the design goals of concepts was to enable compiler emitting meaningful, easy to interpret diagnostics. Here, the concept is used to documenting the contract rather than suppressing unwanted instantiation. Modern compilers understand this specification and are able to explain the problem in pretty clean words.
I admit that "static assertion failed" is not bad. However, the explanation is still indirect, something on the lines, "I tried to instantiate it and hit a static assert. Oops!" While with the concept in the signature, it is straightforward "constraints are not satisfied." The compiler did not even try to instantiate anything; it's simply "no matching overloaded function found."
The beauty of specifying constraints in the signature is that both compilers and humans understand them the same way.