[HN Gopher] A C++ Mixin System
       ___________________________________________________________________
        
       A C++ Mixin System
        
       Author : luu
       Score  : 51 points
       Date   : 2024-11-19 10:58 UTC (3 days ago)
        
 (HTM) web link (jennyjams.net)
 (TXT) w3m dump (jennyjams.net)
        
       | heresie-dabord wrote:
       | It seems messy and even the author of TFA is unconvinced.
       | 
       | How does a mixin compare to _role_ or _interface_ in languages
       | that do not have multiple inheritance?
        
       | mightyham wrote:
       | While I've never really found much practical use for mixins, it
       | is fairly easy to create a runtime system for them in Java. Any
       | interface can become a mixin simply by storing state in a static
       | global hashmap with `this` as the key to the map. Specifically
       | for the map, I would use `Collections.synchronizedMap(new
       | WeakHashMap<>())` so that the map is thread-safe and allows mixin
       | instances to be garbage collected.
        
       | cisters wrote:
       | In a language with ad-hoc polymorphism like C++, mixins seems
       | entirely unnecessary.
       | 
       | You can just declare by convention that a freestanding clone(T x)
       | -> T function should exist for it to be 'cloneable'.
        
         | Rucadi wrote:
         | And just use concepts and call it a day.
        
         | cgh wrote:
         | This "mixin" concept uses the CRTP pattern, as mentioned in the
         | post:
         | https://en.wikipedia.org/wiki/Curiously_recurring_template_p...
         | 
         | It actually does have specific applications. That Wikipedia
         | article shows a good example of polymorphic method chaining. In
         | a former life, I worked with Microsoft's Active Template
         | Library, which is entirely based on this pattern.
        
       | Asooka wrote:
       | Code with types on the right like this makes me very sad
       | static         auto create(const char* data) -> Result<String>
       | 
       | Types are a lot more ergonomic on the left - the return type of a
       | function and the type of a variable are very important for
       | understanding and skimming code. When the return type is on the
       | right, it is physically very far from the name of the object and
       | I have to scan the entire line with my eyes to get the same
       | amount of information I would get by just looking at the left
       | column and scrolling down if it were on the left. I am pretty
       | sure in another 20 years types on the right will be regarded as
       | one of the ergonomic fails of current language design. At least,
       | if have to do this, put the type right under the object name,
       | like so:                   static auto         create(const char*
       | data)         -> Result<String>
       | 
       | Future readers will thank you.
        
         | 3836293648 wrote:
         | Types are only nicer on the left when it isn't also annotated
         | with all the other static constexpr [[nodiscard]] nonsense. And
         | left types are actually greppable seperately from variable
         | declarations.
         | 
         | Having both left and right types is stupid, but as a whole
         | right types are easier to deal with
        
           | winocm wrote:
           | I learned of a cute side effect when one puts the function
           | name on its own line, like above.
           | 
           | In BSD of yore and modern contemporaries, one could often
           | perform `grep '^function'` and end up finding the source file
           | quite easily. I think it also makes using ctags(1) a bit
           | easier too, but not entirely sure on that bit.
        
         | bigstrat2003 wrote:
         | No they won't. Your example is way more unpleasant to read.
        
         | PittleyDunkin wrote:
         | I cannot disagree more strongly. Putting the name of the
         | function (or method) in the middle of the declaration
         | drastically lowers readability.
         | 
         | C-style type declarations were always the most painful part of
         | reading C.
        
         | binary132 wrote:
         | FWIW I completely agree, I think -> rt is a very silly idiom in
         | declarations. It's fine and useful for lambdas.
        
       | cherryteastain wrote:
       | I don't really see the point when C++ already lets you write
       | 
       | void foo(auto& t) { t.bar(); }
       | 
       | which can be called with any class that has the .bar() method
       | anyway.
        
         | Maxatar wrote:
         | Because it can also be called with any class that doesn't have
         | the bar method, and good luck deciphering the compiler error
         | for it when it's nested 3 levels deep into some far corner of
         | the STL.
        
           | lbhdc wrote:
           | That is what concepts fix. It lets you enforce at build time
           | that `t` does have member `.bar()`.
        
       | Svetlitski wrote:
       | > I think the big asterick to all of this design is that my ideal
       | framework would not look like standard C++ but like a slightly
       | weirder Rust stdlib
       | 
       | An interesting option in this space is rpp [1], which bills
       | itself as a "Minimal Rust-inspired C++20 STL replacement"
       | 
       | [1]: https://github.com/TheNumbat/rpp
        
       | tempodox wrote:
       | That `String` leaks memory, it doesn't have a destructor.
        
         | hermitdev wrote:
         | > That `String` leaks memory, [...]
         | 
         | So does the clone...
        
         | rurban wrote:
         | https://github.com/TheNumbat/rpp/blob/main/rpp/string0.h#L92
         | here it is
        
           | asveikau wrote:
           | If omitting it for brevity on a website, they could have just
           | shown the signature and commented out the body ...
        
       | surajrmal wrote:
       | We've used this pattern for years. It definitely delivers in
       | terms of being lower overhead. I will say that compiler errors
       | can be nonsense though.
        
       | Matheus28 wrote:
       | std::optional<T&>
       | 
       | Can't have optional references in C++. Use either
       | std::reference_wrapper, or just a pointer
        
         | cocoto wrote:
         | It is specified previously in the text that support for
         | references would be nice for optionals.
        
           | tialaramex wrote:
           | And unless I'm mistaken C++ 26 gets std::optional<T&> with
           | the preferred representation (ie it's the same size as T&
           | like with Rust's Option<&T> and &T pairing) and the
           | ergonomics are no worse than you'd expect for C++
        
       | DidYaWipe wrote:
       | "Mixin?" What's it mixin'?
        
       ___________________________________________________________________
       (page generated 2024-11-22 23:01 UTC)