Live data from Hacker News

Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

leandromoreira.com

121–130 of 131 posts

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#121
post #116

Earlier quoted context omitted.

I don't see how concepts can emulate signatures to the full extent that the target object can be manipulated as if it conformed to an abstract base, without any wrapper object being required to handle it. Without signatures, we have to use some kind of delegating shim which takes the virtual function calls, and calls the real object. It could be a smart pointer. With signatures, we don't use smart pointers, just "poi…

Here is an example then, assuming you mean this kind of abstrations, #include using namespace std; template concept Speaker = requires (T t) { t.speak(); }; class Duck { public: void speak() const { cout void speaking_animal(const T& animal) { animal.speak(); cout void speaking_farm(const T&... animals) { auto space_adder = [&](auto creature) -> void { creature.speak(); cout Live example, https://godbolt.org/z/vPhf13…

Right, but speaking_animal(x) is not dynamic OOP dispatch; it's a template function that gets instantiated for each animal type.

Moreover, everything here can be done without a concept.

This version of the code builds with g++ -std=c++17. We just get worse diagnostics if we try to use something as a Speaker which doesn't conform.

    #include 

    using namespace std;

    class Duck {
        public:
        void speak() const {
            cout 
    void speaking_animal(const T&  animal) {
        animal.speak();
        cout 
    void speaking_farm(const T&... animals) {
        auto space_adder = [&](auto creature) -> void {
            creature.speak();
            cout 
I was thinking about more something along these lines. But note the double indirection: we end up passing the smart pointer animal_pointer by reference.

We achieve the "signature thing" though in that we take these animal objects and effectively get them to to conform to the common animal_pointer abstract base without their cooperation.

    #include 

    using namespace std;

    class Duck {
    public:
        void speak() const { cout  class animal_pointer_impl : public animal_pointer {
    private:
        T *obj;
    public:
        animal_pointer_impl(T *o) : obj(o) { }
        virtual void speak() const { obj->speak(); }
    };

    void animal_api(const animal_pointer &p)
    {
        p.speak();
 cout  p0(&duck);
        animal_pointer_impl p1(&dog);
        animal_pointer_impl p2(&cat);

        animal_api(p0);
        animal_api(p1);
        animal_api(p2);
    }
animal_api is a regular function, which represents some external API that we don't get to recompile.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#122

Earlier quoted context omitted.

So does the good old Quake 2 rendering API. The game exported a bunch of functions to the renderer via refimport_t and the renderer in return provided functions via refexport_t. The only visible symbol in a rendering DLL is GetRefAPI_t: https://github.com/id-Software/Quake-2/blob/master/client/re... I remember being impressed by this approach, so I shamelessly copied it for my programming game: https://github.com/div…

Pretty sure Half-Life does something pretty similar - all functionality between the game and engine is done via function pointer structs.

The original Half-Life engine, now called Goldsrc, is a heavily modified Quake engine with bits of Quake 2 in there.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#123
post #116

Earlier quoted context omitted.

Here is an example then, assuming you mean this kind of abstrations, #include using namespace std; template concept Speaker = requires (T t) { t.speak(); }; class Duck { public: void speak() const { cout void speaking_animal(const T& animal) { animal.speak(); cout void speaking_farm(const T&... animals) { auto space_adder = [&](auto creature) -> void { creature.speak(); cout Live example, https://godbolt.org/z/vPhf13…

Right, but speaking_animal(x) is not dynamic OOP dispatch; it's a template function that gets instantiated for each animal type. Moreover, everything here can be done without a concept. This version of the code builds with g++ -std=c++17. We just get worse diagnostics if we try to use something as a Speaker which doesn't conform. #include using namespace std; class Duck { public: void speak() const { cout void speaki…

You missed speaking_farm().

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#124
post #83

Earlier quoted context omitted.

Here is my experimental maybe type for C: https://godbolt.org/z/YxnsY7Ted

Six divided by minus one is a "Division by zero" now? Where I come from that's minus six. Good luck to WG14 (or maybe a faction within it?) as they seem to have decided to go make their own C++ competitor now, it's a weird time to do that, but everybody needs a hobby.

Yeah, I was about to add the test for INT_MIN / -1 but got distracted, but also not really the point of the example anyway.

I hope you realize that this is example does not need any complex C++ features.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#125

This is an excellent pattern in C. The Dovecot mail server has many fine examples of the style as well e.g. struct dict dict_driver_ldap = { .name = "ldap", .v = { .init = ldap_dict_init, .deinit = ldap_dict_deinit, .wait = ldap_dict_wait, .lookup = ldap_dict_lookup, .lookup_async = ldap_dict_lookup_async, .switch_ioloop = ldap_dict_switch_ioloop, } }; defines the virtual function table for the LDAP module, and any o…

So does the good old Quake 2 rendering API. The game exported a bunch of functions to the renderer via refimport_t and the renderer in return provided functions via refexport_t. The only visible symbol in a rendering DLL is GetRefAPI_t: https://github.com/id-Software/Quake-2/blob/master/client/re... I remember being impressed by this approach, so I shamelessly copied it for my programming game: https://github.com/div…

This is cargo cult. You can just directly export and import the rendering functions.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#126
post #124

Earlier quoted context omitted.

Six divided by minus one is a "Division by zero" now? Where I come from that's minus six. Good luck to WG14 (or maybe a faction within it?) as they seem to have decided to go make their own C++ competitor now, it's a weird time to do that, but everybody needs a hobby.

Yeah, I was about to add the test for INT_MIN / -1 but got distracted, but also not really the point of the example anyway. I hope you realize that this is example does not need any complex C++ features.

I mean, sure. I read the "noplate" code. Did you ever watch the Mrs Merton show? "So, what first attracted you to the millionaire Paul Daniels?". There's a reason you felt the need to insist that your C language generic containers aren't relying on "complex C++ features" whatever you might decide that means.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#127
post #124

Earlier quoted context omitted.

Yeah, I was about to add the test for INT_MIN / -1 but got distracted, but also not really the point of the example anyway. I hope you realize that this is example does not need any complex C++ features.

I mean, sure. I read the "noplate" code. Did you ever watch the Mrs Merton show? "So, what first attracted you to the millionaire Paul Daniels?". There's a reason you felt the need to insist that your C language generic containers aren't relying on "complex C++ features" whatever you might decide that means.

The issue with C++ is that it is a hyper-complex language that really is a combination of four languages: C with classes, template code, macros, and constexpr code with largely overlapping functionality. It seems to be getting better in amalgamating these different parts, but it is still a mess that annoys me all the time when I try to use it. This complexity is what drove me away. Still there is a unmet need for generic programming in C and I can now do this with macros very well means I can have it without missing this part from C++. So the idea is not to reinvent C++ but to make minor tweaks to C to be able to do similar things in a much simpler way.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#128
post #82

Earlier quoted context omitted.

This will be in C2Y and is already supported by GCC 15: https://godbolt.org/z/szb5bovxq

This is one example. Off the top of my head std.array vs "naked" C arrays, string vs const char*, and let's not forget RAII are all features that just make me never want to work with vanilla C ever again.

For me, std.array seem fundamentally inferior compared to C arrays. A good standard string type is indeed missing, but it is also easy to define one. RAII, I can see, but I also some advantages to have explicit resource deallocation visible in the code and it is not really bothering me too much to write this explicitly.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#129
post #86
post #62

Earlier quoted context omitted.

For C users. And C++ users: In C++ we can declare variable in the while or if statement: https://en.cppreference.com/w/cpp/language/while https://en.cppreference.com/w/cpp/language/if It's value is the value of the decision. This is not possible with C [1]. Since C++17 the if condition can contain an initializer: Ctrl+F if statements with initializer https://en.cppreference.com/w/cpp/language/if Which sounds like the…

Declaring a variable in a loop or if statement is supported since C99: https://en.wikipedia.org/wiki/C99 Also in Java: https://www.geeksforgeeks.org/for-loop-java-important-points...

Regarding Java:

It is possible that you confuse while- and for statements?

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#130
post #93
post #86

Earlier quoted context omitted.

Declaring a variable in a loop or if statement is supported since C99: https://en.wikipedia.org/wiki/C99 Also in Java: https://www.geeksforgeeks.org/for-loop-java-important-points...

No, declaring a variable in a `for` loop is supported in C99 but you can't do if-init.

You do :)

My post was about while and if and you repeatingly bring up for. The for statement is another statement.

Post reply on HN