-
Notifications
You must be signed in to change notification settings - Fork 252
Use templates to avoid repetition, and to add type safety #1236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Use templates to avoid repetition, and to add type safety #1236
Conversation
cd88259 to
68fb6b6
Compare
|
Am Montag, dem 10.03.2025 um 09:39 -0700 schrieb Alejandro Colomar:
@alejandro-colomar commented on this pull request.
In lib/atoi/strtoi/strton.h:
> + \
+ if (*endp == s) \
+ *status = ECANCELED; \
+ else if (errno == ERANGE || n < min || n > max) \
+ *status = ERANGE; \
+ else if (**endp != '\0') \
+ *status = ENOTSUP; \
+ else \
+ *status = 0; \
+ \
+ errno = e; \
+ \
+ return MAX(min, MIN(max, n)); \
+}
+//#enddef
+#define STRTON(T, ...) STRTON__ ## T(__VA_ARGS__)
I could actually fix the off-by-one attributes by moving the T to the end of the parameter list, and using the explicit parameter list here instead of ....
I would just write it as STRTON__ ## in the definition
instead of using the STRTON macro, which would get rid
fo the off-by-one. I also hides less of mechanism which
I think is good.
I also wonder whether you can replace the code in
the c file with something such as
extern inline typeof(STRTON__ ## uintmax_t) STRTON__ ## uintmax_t;
instead of repeating all the arguments.
… —
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
The good thing about using STRTON() is that it looks like a function definition. grepc(1) (my regex-based program for grepping C code) finds it just fine. However, if I use ##, then the regex doesn't find it.
I'm not too worried, since that repetition is checked by the compiler. Also, the same argument applied: regex-based programs will find the prototypes using STRTON(). https://www.alejandro-colomar.es/src/alx/alx/grepc.git/tree/bin/grepc |
Actually, I correct myself. grepc(1) is able to grep the template definition with $ grepc -h CMP .
#define CMP(T) cmp__ ## T // For use as a callback$ grepc -hC1 'cmp__ ## T' .
#def template_cmp(T)
inline int
cmp__ ## T(const void *key, const void *elt)
{
const T *k = key;
const T *e = elt;
if (*k < *e)
return -1;
if (*k > *e)
return +1;
return 0;
}
#enddefSo, I'll follow your suggestion and make it explicit that I'm using |
No, you can't. search/cmp/cmp.c:12:28: error: stray '##' in program
12 | extern inline typeof(CMP__ ## int) CMP__ ## int;
| ^~
search/cmp/cmp.c:12:22: error: 'CMP__' undeclared here (not in a function); did you mean 'CMP'?
12 | extern inline typeof(CMP__ ## int) CMP__ ## int;
| ^~~~~
| CMP
search/cmp/cmp.c:12:27: error: expected ')' before 'int'
12 | extern inline typeof(CMP__ ## int) CMP__ ## int;
| ~ ^ ~~~
| )Concatenation doesn't work outside of macros. I guess I'll either concatenate myself, or write a small macro for that. |
084f3d7 to
e287e1b
Compare
lib/search/l/lfind.c
Outdated
| extern inline void *lfind_(const void *k, const void *a, size_t n, size_t ksize, | ||
| typeof(int (const void *k, const void *elt)) *cmp); | ||
| extern inline const int *LFIND__int(size_t n; | ||
| const int *k, const int a[n], size_t n); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lfind.c
Outdated
| extern inline const int *LFIND__int(size_t n; | ||
| const int *k, const int a[n], size_t n); | ||
| extern inline const long *LFIND__long(size_t n; | ||
| const long *k, const long a[n], size_t n); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lfind.c
Outdated
| extern inline const long *LFIND__long(size_t n; | ||
| const long *k, const long a[n], size_t n); | ||
| extern inline const u_int *LFIND__u_int(size_t n; | ||
| const u_int *k, const u_int a[n], size_t n); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lfind.c
Outdated
| extern inline const u_int *LFIND__u_int(size_t n; | ||
| const u_int *k, const u_int a[n], size_t n); | ||
| extern inline const u_long *LFIND__u_long(size_t n; | ||
| const u_long *k, const u_long a[n], size_t n); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lfind.h
Outdated
| /* lfind(3) wants a pointer to n for historic reasons. */ \ | ||
| return lfind(k, a, &n, sizeof(T), CMP(T)); \ | ||
| } | ||
| template_LFIND(int); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lsearch.h
Outdated
| { \ | ||
| lsearch(k, a, n, sizeof(T), CMP(T)); \ | ||
| } | ||
| template_LSEARCH(int); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lsearch.h
Outdated
| lsearch(k, a, n, sizeof(T), CMP(T)); \ | ||
| } | ||
| template_LSEARCH(int); | ||
| template_LSEARCH(long); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lsearch.h
Outdated
| } | ||
| template_LSEARCH(int); | ||
| template_LSEARCH(long); | ||
| template_LSEARCH(u_int); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/l/lsearch.h
Outdated
| template_LSEARCH(int); | ||
| template_LSEARCH(long); | ||
| template_LSEARCH(u_int); | ||
| template_LSEARCH(u_long); |
Check notice
Code scanning / CodeQL
Short global name
lib/search/sort/qsort.h
Outdated
| template_QSORT(int); | ||
| template_QSORT(long); | ||
| template_QSORT(u_int); | ||
| template_QSORT(u_long); |
Check notice
Code scanning / CodeQL
Short global name
12ff7c4 to
7716e5e
Compare
7716e5e to
37ea130
Compare
37ea130 to
4aeb169
Compare
818eb20 to
40b10cf
Compare
f101a61 to
25091f3
Compare
25091f3 to
8dd0396
Compare
0a3d6a1 to
d32bec8
Compare
d32bec8 to
d8cab62
Compare
97fe3e3 to
7f60d6d
Compare
This macro is useful to implement QChar versions of functions. See ISO C23 for a description of what QChar is. Signed-off-by: Alejandro Colomar <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
It won't hurt; if the type is convertible, it will be accepted; and if it's not convertible, the compiler will reject it at call site. This 'default' branch allows converting a QChar** into a char**. Signed-off-by: Alejandro Colomar <[email protected]>
This allows grepping for casts more easily. It also reduces the damage of a bogus cast. Signed-off-by: Alejandro Colomar <[email protected]>
This adds readability at call site, and simplifies the implementation. Signed-off-by: Alejandro Colomar <[email protected]>
We don't need the return value of LSEARCH() at all, so let's remove it. We don't need to modify the return value of LFIND(), so make it const. Signed-off-by: Alejandro Colomar <[email protected]>
We can use _Generic() on the element type, without using a pointer type. Signed-off-by: Alejandro Colomar <[email protected]>
ecd4e78 to
8458aa1
Compare
Signed-off-by: Alejandro Colomar <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
d86fba1 to
6cfae11
Compare
Signed-off-by: Alejandro Colomar <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
This allows us to get rid of ({}), which is a GNU extension.
Signed-off-by: Alejandro Colomar <[email protected]>
6cfae11 to
c3c6ede
Compare
Cc: @uecker
Cc: @chrisbazley
This is an experiment about mimicking templates in C with macros. If we get rid of the trailing
\, this looks quite nice.