Mine is that the useState hook is an actual plague on the entire React ecosystem. Regardless of your opinions of React, if you wanna use something then use it right.

you are viewing a single comment's thread
view the rest of the comments
[–] 1 point 2 weeks ago (5 children)

B and C can't share any other attributes without duplication of code. There's also no strict enforcement of inheritance.

  • source
  • parent
  • hideshow 5 child comments
  • [–] 2 points 2 weeks ago* (4 children)

    It was a simplified example.

    B and C can’t share any other attributes without duplication of code

    struct A {
        [[nodiscard]] virtual std::uint32_t DoSomething() = 0;
    };
    
    struct B : A {
        std::uint32_t DoSomething() override { 
            return 0;
        }
    };
    
    int main() {
        B b;
        b.DoSomething(); //no warning
    }
    

    even if you use virtual attributes aren't inherited.

    If you ment members instead of attributes this is unrelated to virtual:

    struct A {
        std::uint32_t a;
    };
    
    
    struct B : A {
        void DoSomething() { 
            std::println("B"); 
        }
    };
    
    struct C : A {
        void DoSomething() { 
            std::println("C"); 
        }
    };
    

    Now the member is shared and it works fine and there is no virtual.

    There’s also no strict enforcement of inheritance.

    True, but neither is there when just using virtual:

    struct A {
        virtual void DoSomething() = 0;
    };
    
    struct B : A {
    
    };
    

    This compiles fine if final is not added.

    Not that its an issue as reflection has solved this problem:

    consteval std::string_view HasMethods(std::meta::info impl, std::meta::info iface) {
        constexpr auto ctx = std::meta::access_context::unchecked();
        for (auto fn : members_of(iface, ctx)) {
            if (!is_function(fn) || is_special_member_function(fn)) continue;
            bool found = false;
            for (auto cand : members_of(impl, ctx))
                if (is_function(cand) && has_identifier(cand) && identifier_of(cand) == identifier_of(fn) && type_of(cand) == type_of(fn))
                    found = true;
            if (!found)
                return std::define_static_string(std::string(identifier_of(impl)) + " is missing " + display_string_of(fn));
        }
        return {};
    }
    
    
    struct A {
        void DoSomething();
    };
    
    struct B  {
    
    };
    static_assert(HasMethods(^^B, ^^A).empty(), HasMethods(^^B, ^^A));
    
    // g++ -std=c++26 -freflection main.cpp
    // main.cpp:30:41: error: static assertion failed: B is missing void A::DoSomething()
    // 30 | static_assert(HasMethods(^^B, ^^A).empty(), HasMethods(^^B, ^^A));
    

    Now you get the strict enforcement of inheritance and no virtual.

  • source
  • parent
  • hideshow 4 child comments
  • [–] 1 point 2 weeks ago (3 children)

    LOL. That mess is somehow better?

  • source
  • parent
  • hideshow 3 child comments
  • [–] 0 points 2 weeks ago (2 children)

    One utility function somewhere vs runtime polymorphism everywhere?

    Yes.

  • source
  • parent
  • hideshow 2 child comments
  • [–] 0 points 2 weeks ago (1 child)

    You just reinvented polymorphism with extra jank.

  • source
  • parent
  • hideshow 1 child comment
  • [–] 0 points 2 weeks ago*

    How is it jank to put one utility function in a file somewhere you never need to look at again?

    That is if you even want to do the assert since if the type doesn't have the method it won't compile in the calling function anyway but since you mentioned the strict check it's fully possible.

    And why isn't it jank to write virtual, final, and override everywhere and have the entire codebase infested with vtables.

  • source
  • parent