@@ -96,6 +96,9 @@ typedef struct ns_list {
9696 * always assign returned entry pointers to a properly typed pointer variable.
9797 * This assignment will be then type-checked where the compiler supports it, and
9898 * will dereference correctly on compilers that don't support this extension.
99+ *
100+ * If you need to support C++03 compilers that cannot return properly-typed
101+ * pointers, such as IAR 7, you need to use NS_LIST_TYPECOERCE to force the type.
99102 * ~~~
100103 * NS_LIST_HEAD(example_entry_t, link) my_list;
101104 *
@@ -199,6 +202,27 @@ union \
199202#define NS_LIST_TYPECAST_ (list, val ) (0 ? (list)->type : (val))
200203#endif
201204
205+ /* * \brief Macro to force correct type if necessary.
206+ *
207+ * In C, doesn't matter if NS_LIST_TYPECAST_ works or not, as it's legal
208+ * to assign void * to a pointer. In C++, we can't do that, so need
209+ * a back-up plan for C++03. This forces the type, so breaks type-safety -
210+ * only activate when needed, meaning we still get typechecks on other
211+ * toolchains.
212+ *
213+ * If a straight assignment of a ns_list function to a pointer fails
214+ * on a C++03 compiler, use the following construct. This will not be
215+ * required with C++11 compilers.
216+ * ~~~
217+ * type *elem = NS_LIST_TYPECOERCE(type *, ns_list_get_first(list));
218+ * ~~~
219+ */
220+ #if defined(NS_LIST_PTR_TYPE_) || !defined(__cplusplus)
221+ #define NS_LIST_TYPECOERCE (type, val ) (val)
222+ #else
223+ #define NS_LIST_TYPECOERCE (type, val ) (type) (val)
224+ #endif
225+
202226/* * \brief Internal macro to check types of input entry pointer. */
203227#define NS_LIST_TYPECHECK_ (list, entry ) \
204228 (NS_PTR_MATCH_((list)->type, (entry), " incorrect entry type for list" ), (entry))
@@ -480,7 +504,8 @@ typedef struct ns_list_link {
480504 * \param list `(const list_t *)` Pointer to list - evaluated multiple times.
481505 */
482506#define ns_list_foreach (type, e, list ) \
483- for (type *e = ns_list_get_first(list); e; e = ns_list_get_next(list, e))
507+ for (type *e = NS_LIST_TYPECOERCE(type *, ns_list_get_first(list)); \
508+ e; e = NS_LIST_TYPECOERCE(type *, ns_list_get_next(list, e)))
484509
485510/* * \brief Iterate forwards over a list, where user may delete.
486511 *
@@ -500,25 +525,26 @@ typedef struct ns_list_link {
500525 * \param list `(list_t *)` Pointer to list - evaluated multiple times.
501526 */
502527#define ns_list_foreach_safe (type, e, list ) \
503- for (type *e = ns_list_get_first(list), *_next##e; \
504- e && (_next##e = ns_list_get_next(list, e), true ); e = _next##e)
528+ for (type *e = NS_LIST_TYPECOERCE(type *, ns_list_get_first(list) ), *_next##e; \
529+ e && (_next##e = NS_LIST_TYPECOERCE(type *, ns_list_get_next(list, e) ), true ); e = _next##e)
505530
506531/* * \brief Iterate backwards over a list.
507532 *
508533 * As ns_list_foreach(), but going backwards - see its documentation.
509534 * Iterating forwards is *slightly* more efficient.
510535 */
511536#define ns_list_foreach_reverse (type, e, list ) \
512- for (type *e = ns_list_get_last(list); e; e = ns_list_get_previous(list, e))
537+ for (type *e = NS_LIST_TYPECOERCE(type *, ns_list_get_last(list)); \
538+ e; e = NS_LIST_TYPECOERCE(type *, ns_list_get_previous(list, e)))
513539
514540/* * \brief Iterate backwards over a list, where user may delete.
515541 *
516542 * As ns_list_foreach_safe(), but going backwards - see its documentation.
517543 * Iterating forwards is *slightly* more efficient.
518544 */
519545#define ns_list_foreach_reverse_safe (type, e, list ) \
520- for (type *e = ns_list_get_last(list), *_next##e; \
521- e && (_next##e = ns_list_get_previous(list, e), true ); e = _next##e)
546+ for (type *e = NS_LIST_TYPECOERCE(type *, ns_list_get_last(list) ), *_next##e; \
547+ e && (_next##e = NS_LIST_TYPECOERCE(type *, ns_list_get_previous(list, e) ), true ); e = _next##e)
522548
523549/* * \hideinitializer \brief Count entries on a list
524550 *
0 commit comments