Struct Embedding in Cilk

Cilk supports struct-like constructs called “hyperobjects” which can be used to express composition of types. This concept is similar to struct embedding in other languages.

#include <cilk/cilk.h>
#include <stdio.h>
#include <string.h>

// Define a base hyperobject
typedef struct {
    int num;
} base;

// Function to describe the base
char* describe_base(base* b) {
    static char buffer[50];
    sprintf(buffer, "base with num=%d", b->num);
    return buffer;
}

// Define a container hyperobject that includes base
typedef struct {
    base b;
    char* str;
} container;

int main() {
    // Create a container instance
    container co;
    co.b.num = 1;
    co.str = "some name";

    // Access the base's fields directly on co
    printf("co={num: %d, str: %s}\n", co.b.num, co.str);

    // Alternatively, we can spell out the full path using the embedded type name
    printf("also num: %d\n", co.b.num);

    // Call the describe function for the base
    printf("describe: %s\n", describe_base(&co.b));

    // In Cilk, we don't have direct support for interfaces,
    // but we can simulate similar behavior using function pointers
    typedef char* (*describer_func)(void*);
    describer_func d = (describer_func)describe_base;
    printf("describer: %s\n", d(&co.b));

    return 0;
}

To compile and run this Cilk program:

$ cilk++ struct_embedding.cilk -o struct_embedding
$ ./struct_embedding
co={num: 1, str: some name}
also num: 1
describe: base with num=1
describer: base with num=1

In this Cilk version, we’ve simulated struct embedding using nested structs. The container struct includes a base struct as its first member, allowing direct access to base members through the container instance.

We’ve also simulated the concept of interfaces and method embedding using function pointers. The describe_base function acts as a method for the base struct, and we can call it on the container instance as well.

Note that Cilk doesn’t have built-in support for some object-oriented features like interfaces or method embedding, so we’ve approximated these concepts using C-style structs and function pointers. The overall structure and functionality remain similar to the original example, showcasing how to compose types and share behavior in Cilk.