On forcing all derived classes to implement a specific non-virtual method, part 2
https://devblogs.microsoft.com/oldnewthing/20260828-00/?p=11265416
u/Alduish 2d ago
But why ?
Virtual classes have a reason to exist, if you cast the derived object back to the base class (a function that can opperate on any derived objects of this virtual class) then if the function isn't virtual you're gonna call the deleted function and the whole trick will have been useless.
14
2
u/SubstituteCS 1d ago
Virtual method overhead.
For example, I have a pointer library that I wrote that wraps arbitrary addresses known to be valid of T.
These pointers have some variation in their reset and release methods.
It would be very stupid to use virtual methods for reset and release as each pointer would become the size of two pointers as the class would store both the pointer we are wrapping, and a pointer to the virtual method table.
-1
u/pjmlp 2d ago
Because many people go out of their way avoiding C++ features, at which point I always tell them just to use C, if they dislike C++ so much.
12
u/_Fibbles_ 2d ago
I very much want to be a fly on the wall when you tell Raymond Chen that he should use C because he clearly dislikes C++.
-2
u/pjmlp 1d ago
If you look into MFC versus OWL or VCL, the Microsoft C++ culture really clearly wants to write C with Classes and nothing else.
One needs to look into .NET for what Borland was doing with C++ already in Turbo Vision.
A spirit that permutates among the countless reboots of COM frameworks, versus C++ Builder as well.
Sure, are you arranging the meeting?
5
u/Gungan_Boss_Nass 2d ago
Tweaking the implementation to provide better compiler error messages is another example of compiler error message metaprogramming, which is one of the under-appreciated aspects of authoring a code library.
Possible errors is an interesting sub-category here. I can write requires or static_assert and provide an escape hatch for the caller to bypass it if it's not an error. That covers the 95% probability cases, but feels excessive for the 70% probability cases.
[[deprecated("This is probably wrong")]] with some SFINAE works better for those. You can build and test and only turn off the warning when you're really sure.
•
u/NilacTheGrim 2h ago
Meh. Kinda neat, but not sure how i feel about this.
If you really want to enforce some method be implemented in a certain set of related classes, then presumably you are polymorphic somewhere in some way in your code -- whether this be through traditional polymorphism via vtables, or polymorphism via templates.
If you're using vtables you don't need this technique since in that case you just do the usual virtual void Convert() = 0.
If you're using templates to achieve the polymorphism then you also don't need this because you can use concepts and/or requires clauses to enforce this.
But I guess the usage here is more succinct although it sort of makes the code weirder to maintain -- you have code that CONSUMES these classes that cares about the .Convert() method existing -- but they don't enforce that.
Instead you put the onus on the base class to enforce that "for reasons" that aren't immediately clear when reading the base class.
I would rather just use a concept or a requires clause at the CONSUMING end of this class hierarchy closer to the code that cares whether .Convert() exits or not... it's easier to maintain and reason about if you ask me.
But this is neat.. I'll give Mr. Chen that.
-1
u/Ateist 2d ago edited 2d ago
winrt::Windows::UI::Xaml::Interop::TypeName const&
WTF is this coding style?!
Examples are extremely hard to read due to multi-layered namespace issues like this.
This is well past the point where it serves its purpose and into the "extremely harmful" territory.
How does code like this pass any code review?
7
u/SyntheticDuckFlavour 2d ago
Disagree. Namespaces like these explicitly organises and communicates which component you are interacting with at any given moment. It also avoids clashes with class definitions and type names. Furthermore, APIs can to grow independently without the worrying about polluting other namespaces or introducing new conflicts with existing class definitions. Bit of a nothingburger, really. You can always just drop
using namespace winrt::Windows::UI::Xaml::Interopwithin an implementation scope.-1
u/Ateist 2d ago edited 2d ago
It doesn't help in the slightest if you can't read and understand the damn function because it keeps filling your mind's context window with irrelevant things - I keep losing the main point because of all that verbosity.
Reading the code is already the most difficult part of the job - and code like this makes it impossible.
If you really, really need to accommodate poorly built APIs like that
You can always just drop using namespace winrt::Windows::UI::Xaml::Interop within an implementation scope.
it shouldn't be optional - it should be mandatory.
and it's better to do
using Interop = winrt::Windows::UI::Xaml::Interopto improve readability without polluting the namespace with things you don't want.
It might also be better to dousing namespace winrt::Windowsto reuse the common part.
2
u/mredding 1d ago
It doesn't help in the slightest if you can't read and understand the damn function because it keeps filling your mind's context window with irrelevant thing
If...
I look right past it. I don't give a damn what these things are because I don't have to know. Just symbolically, it's a thing - in a template parameter.
You need to train your brain to ignore the irrelevant.
and it's better to do [...] to improve readability without polluting the namespace
And that's what OP said, and is agreeable. I'd do it, and I do it even when writing example code on Reddit.
It might also be better to do
No, this is a contradiction of your previous point that avoiding namespace pollution is a virtue. It's better to alias the namespace.
2
u/SyntheticDuckFlavour 1d ago
it shouldn't be optional - it should be mandatory.
Disagree. Implicit
using namespacewill create clashes. There is a reason whyusing namespacein header scope is considered bad practice and it should be only used in implementation scope.3
u/teerre 1d ago
It's hard to read because it's spells exactly where the code is coming from? How is that possible? Do you define "hard to read" by how many characters is has?
The hard to read version of this would be if it was imported from some header and you had no idea which
6
u/Ateist 1d ago
It's hard to read because the essential parts are buried under a ton of irrelevant staff.
Instead of having everything in single, clearly understandable portions it mixes in lots of information that is no way essential to the function in question.
The only portion in that line that play any part is:
Typename const&0
u/teerre 1d ago
What? How is the namespace irrelevant? It's literally where the type resides
2
u/Ateist 1d ago
When you are writing note to your neghbour you don't start his address with
Milky_Way_Galaxy:Solar_System:Planet_Earth:United_States_Of_America:California:HollywoodYou just state "Apartment 12" so that it doesn't go to another neigbour next door.
1
u/teerre 1d ago
I mean, disregarding the fact that the whole mail system worldwide indeed requires full addresses, what do addresses in notes to neighbors have to with this?
1
u/EmbarkVatyx 1d ago
They are just saying the code in the post was illustrating a point which was hard to follow due to the verbosity of the type (notably the specific type is irrelevant to the broader point). If the type was named T instead it would be easier to see what’s going on. I had the same issue.
•
u/NilacTheGrim 2h ago
I agree. Namespaces shouldn't be this super complicated taxonomy like in biology. It's really bad usage of namespaces.
0
u/sephirostoy 2d ago
East const doesn't help neither.
9
u/lonkamikaze 2d ago
It actually does if you read types right to left. Reference to const TypeName instead of const (skip all the namespaces) TypeName reference.
31
u/Electronic_Tap_8052 2d ago
Huh. I usually accomplish this with a template type that has a function declaration but no implementation. That way there's no 'base class' at all to worry about, and it's all resolved at compile time.
I call it poor man's inheritance.