Skip to content

Use templates to avoid repetition, and to add type safety#1236

Draft
alejandro-colomar wants to merge 14 commits intoshadow-maint:masterfrom
alejandro-colomar:template
Draft

Use templates to avoid repetition, and to add type safety#1236
alejandro-colomar wants to merge 14 commits intoshadow-maint:masterfrom
alejandro-colomar:template

Conversation

@alejandro-colomar
Copy link
Collaborator

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.

@uecker
Copy link
Contributor

uecker commented Mar 10, 2025 via email

@alejandro-colomar
Copy link
Collaborator Author

alejandro-colomar commented Mar 10, 2025

Am Montag, dem 10.03.2025 um 09:39 -0700 schrieb Alejandro Colomar:
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.

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 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.

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

@alejandro-colomar
Copy link
Collaborator Author

alejandro-colomar commented Mar 12, 2025

Am Montag, dem 10.03.2025 um 09:39 -0700 schrieb Alejandro Colomar:
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.

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 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.

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

@uecker

Actually, I correct myself. grepc(1) is able to grep the template definition with ## in its name as long as you include that in the search term.

$ 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;
}
#enddef

So, I'll follow your suggestion and make it explicit that I'm using ## in the template definition. It will make the machinery more readable.

@alejandro-colomar
Copy link
Collaborator Author

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.

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.

@alejandro-colomar alejandro-colomar force-pushed the template branch 3 times, most recently from 084f3d7 to e287e1b Compare March 13, 2025 02:04
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

Poor global variable name 'k'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo).
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

Poor global variable name 'k'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo).
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

Poor global variable name 'k'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo).
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

Poor global variable name 'k'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo).
/* 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

Poor global variable name 'k'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo).
{ \
lsearch(k, a, n, sizeof(T), CMP(T)); \
}
template_LSEARCH(int);

Check notice

Code scanning / CodeQL

Short global name

Poor global variable name 'k'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo).
lsearch(k, a, n, sizeof(T), CMP(T)); \
}
template_LSEARCH(int);
template_LSEARCH(long);

Check notice

Code scanning / CodeQL

Short global name

Poor global variable name 'k'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo).
}
template_LSEARCH(int);
template_LSEARCH(long);
template_LSEARCH(u_int);

Check notice

Code scanning / CodeQL

Short global name

Poor global variable name 'k'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo).
template_LSEARCH(int);
template_LSEARCH(long);
template_LSEARCH(u_int);
template_LSEARCH(u_long);

Check notice

Code scanning / CodeQL

Short global name

Poor global variable name 'k'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo).
template_QSORT(int);
template_QSORT(long);
template_QSORT(u_int);
template_QSORT(u_long);

Check notice

Code scanning / CodeQL

Short global name

Poor global variable name 'a'. Prefer longer, descriptive names for globals (eg. kMyGlobalConstant, not foo).
@alejandro-colomar alejandro-colomar changed the title lib/atoi/strtoi/: STRTON(): Add template Use templates to replace macros Mar 13, 2025
@alejandro-colomar alejandro-colomar changed the title Use templates to replace macros Use templates to avoid repetition, and to add type safety Mar 13, 2025
@alejandro-colomar alejandro-colomar force-pushed the template branch 2 times, most recently from 12ff7c4 to 7716e5e Compare March 13, 2025 21:37
@alejandro-colomar alejandro-colomar force-pushed the template branch 5 times, most recently from 818eb20 to 40b10cf Compare June 2, 2025 09:32
@alejandro-colomar alejandro-colomar force-pushed the template branch 4 times, most recently from f101a61 to 25091f3 Compare June 7, 2025 18:11
@alejandro-colomar alejandro-colomar force-pushed the template branch 2 times, most recently from 0a3d6a1 to d32bec8 Compare July 20, 2025 14:36
@alejandro-colomar alejandro-colomar force-pushed the template branch 4 times, most recently from 2b74192 to 5550350 Compare November 12, 2025 11:21
@alejandro-colomar alejandro-colomar force-pushed the template branch 3 times, most recently from 116ccb3 to f91d495 Compare November 19, 2025 21:37
@alejandro-colomar alejandro-colomar force-pushed the template branch 2 times, most recently from 8af07c0 to a70fa5f Compare November 28, 2025 12:28
@alejandro-colomar alejandro-colomar force-pushed the template branch 2 times, most recently from bb0de08 to 591deb0 Compare December 7, 2025 14:06
@alejandro-colomar alejandro-colomar self-assigned this Dec 11, 2025
@alejandro-colomar alejandro-colomar force-pushed the template branch 2 times, most recently from bd1ece0 to 4d254ac Compare February 26, 2026 16:45
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 <alx@kernel.org>
This allows grepping for casts more easily.
It also reduces the damage of a bogus cast.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
We don't need the return value of lsearch_T() at all; let's remove it.
We don't need to modify the return value of lfind_T(); make it const.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This allows us to get rid of ({}), which is a GNU extension.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants