How to have a "generic" struct in a data structure

Here’s the code I’m having the issue with:

pub fn ParseFunctionPointer(comptime T: type) type {
    return *const fn (arg: []const u8) anyerror!T;
}

pub fn Arg(comptime T: type) type {
    return struct {
        parse_fn: ?ParseFunctionPointer(T),
        basename: []const u8,
        config: ArgConfig,

        const Self = @This();

        pub fn init(comptime parse_fn: ?ParseFunctionPointer(T), comptime basename: []const u8, comptime config: ArgConfig) ArgError!Self {
            // ...

            return .{
                .parse_fn = parse_fn,
                .config = config,
                .basename = basename,
            };
        }
    };
}

// ...

pub const Parser = struct {
    args: std.ArrayList(Arg), // <--- error: expected type 'type', found 'fn (comptime type) type'
    allocator: mem.Allocator,

    pub fn init(allocator: mem.Allocator) !Parser {
        const args = std.ArrayList(Arg).init(allocator);

        return .{
            .args = args,
            .allocator = allocator,
        };
    }
    
    // ...
};

I understand why it’s an issue, but I’m not sure what the actual solution is.

I’ve spent a bit of time looking at the way std.format.format uses anytype for its list of formatter args, but I don’t really understand what it’s doing.

What is the actual problem you are trying to solve? Why do you think you need a list of generic type instances to solve this problem?

1 Like

I’m trying to write (yet another) CLI-arg parsing library just for fun.

My idea was to have a Parser struct that holds some Arg(T), where an Arg(T) would be able to parse the argument to a specific type (hence why I was trying to store the parse function pointer).

I don’t necessarily think I need a list of generics to solve this, but I’m not sure how I can get a generic type from a []const u8. I guess, realistically, one probably only needs a handful of types, so I could just have separate IntArg, FloatArg, EnumArg, or whatever, I just wasn’t sure if there was a way to do what I originally wanted (where a user of the library could provide their own parsing function).

1 Like

I’ve done something pretty close to this if you wanna check it out here. There’s also a guide that explains it a bit.

1 Like

Hello @bwbuhse
welcome to ziggit :slight_smile:

You cannot pass a function to ArrayList because a type is expected.
You can call Arg to get a type, but then you need the Arg parameter T:

std.ArrayList(Arg(T)),

A good starting point is:

  • to eliminate T parameter from Arg.
  • make it work for a single case (such as integers or strings)
  • then decide how to support more cases: using anytype, by a function pointer, by an interface or generics.
4 Likes

Fair enough, I’ll give a smaller non-generic scope a shot, first :slight_smile:

Thank you! I chose the exact same variable name as you even, haha. I’ll definitely take a look at how you did it.

1 Like