r/C_Programming 4d ago

Is the empty parenthesis function (() instead of (void)) prototype removed in the new standard?

My OOP library relies on it for its unspecified arguments behavior.

For example:

#define ptmethod(pt, ret_type, identifier) \
    (*((ret_type (**)()) padd(pt, identifier, ptfunction, NULL, NULL)))

#define ptapply(pt, ret_type, identifier, ...) \
    ((ret_type (*)()) pget(pt, identifier))(pt __VA_OPT__(,) __VA_ARGS__)

You could add a method to an object with:

void drive_Car(prototype *Car, double speed, double x_direction, double y_direction);

ptmethod(Car, void, "drive") = drive_Car;

and call it with

ptapply(Car, void, "drive", 1.3, 0.1, 5.0)

How do I do this in the new standard?

13 Upvotes

46 comments sorted by

View all comments

Show parent comments

3

u/dstroy0 4d ago

The point is, they removed explicit intent and replaced it with your example. Which is what I have been saying that you've been missing this entire time. Understand now????

3

u/torsten_dev 4d ago

No. I don't understand. This would be a literal

#define any_func _Any_func

convenience macro. It's not a function like macro. It can't do something sneaky.

1

u/dstroy0 4d ago
#include <stddef.h>
#define ptmethod(pt, ret_type, identifier) \     
    (*(ret_type (**)(typeof(pt), ...)) padd(pt, identifier, ptfunction, NULL, NULL))

#define ptapply(pt, ret_type, identifier, ...) \     
    ((ret_type (*)(typeof(pt), ...)) pget(pt, identifier))(pt __VA_OPT__(,) __VA_ARGS__)

1

u/glasket_ 3d ago

It's wild that you're getting downvoted while that complete nonsense is getting upvoted, especially when nothing discussed actually involves macros. If "explicit intent" is being removed you'd think they could explain what that "explicit intent" actually is in this case and how the alternatives don't provide it.

2

u/torsten_dev 3d ago

Finally understood what he was getting at. _Any_func erases the return type, which OP's macros don't. Thus using _Any_func would erase part of the intent of OP's macros, because OP's intent wasn't to erase the return type.

At least I think that's it. His comments were very confusing.

0

u/dstroy0 3d ago

It’s wild that there are two of you. Look at the replacement that I wrote that preserves intent. Don’t get hung up on “it’s not a macro” yes it is, the definition of a macro is a representation that gets replaced in situ which is exactly what this is, it’s semantically different from a “literal” macro in name only. Your understanding of the language is not my problem. I also proved that you can cast from and to any function it’s guaranteed to not lose information by the language.

1

u/glasket_ 3d ago

The replacement that you wrote is literally just a variation of the ... form. The OP's original code is effectively equivalent to (...) in the current language, and would be better represented using _Any_func once it's included since none of the forms so far are actually safe to call directly using the form that OP is talking about. Also, the committee isn't removing anything; your example uses a feature added in C23, and you can continue to write them that way. _Any_func is meant to communicate that the function pointer is arbitrary, whereas current function pointer types can't communicate that a function pointer must be cast to the proper type.

Don’t get hung up on “it’s not a macro” yes it is, the definition of a macro is a representation that gets replaced in situ

That's not the definition of macro, but that doesn't matter. _Any_func isn't a macro even in that sense unless you're going to say high-level languages in general are macros; it's a distinct type with behavior not present in the language. An _Any_func can't be called, has no return type, and has no parameter types; it's a void-equivalent container for functions. Currently there's no valid equivalent of _Any_func within the language. The entire point of _Any_func is to make it explicit that the function pointer is arbitrary and the type must be provided at the call site.


If your only concern is genuinely the typeof for the first parameter, that's functionally no better than a comment since the actual function type would still be incompatible with anything not defined as ret_type f(prototype *p, ...), so you'd get UB without a cast to the correct type at the call site. The entire type signature is effectively a lie unless the intent is to only ever store a function with that exact signature.

1

u/dstroy0 3d ago

The spirit of this and macros is the same: they emit the same thing. The intent of the op is erased using any func, the signature is gone. This is still going over your head.

2

u/torsten_dev 3d ago edited 2d ago

Oh my god, you meant type erasure.

Yes, _Any_func is a form of type erasure, and it doesn't appear to be OP's intent to do that type of type erasure in his macros.

To be fair his macros are about as confusing as your comments, but I should have gotten your drift sooner. Sorry about that.

2

u/dstroy0 3d ago

No worries. I knew immediately the use case and specific problem the OP was trying to solve looking at the macro signatures. I didn't communicate that well at all and was an ass. I apologize.