summaryrefslogtreecommitdiffhomepage
path: root/examples
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2022-11-05 20:53:55 +0100
committerTyge Løvset <[email protected]>2022-11-05 20:53:55 +0100
commitc230e4cd830de22fad2f7085d968d905dadc7418 (patch)
tree224173728e5b3bb218148166593e00a59d811119 /examples
parentf36740ba450c4c677863dd86ec94bba128aad574 (diff)
downloadSTC-modified-c230e4cd830de22fad2f7085d968d905dadc7418.tar.gz
STC-modified-c230e4cd830de22fad2f7085d968d905dadc7418.zip
Added possibility to have per container-instance customizable compare/lookup functions (cmp, less, eq, hash) for priority queue and associative containers. Is achived by embedding the container in a struct along with function pointer(s) which can be accessed through the c_container_of() macro. See the updated cpque.c example in the examples folder.
Diffstat (limited to 'examples')
-rw-r--r--examples/cpque.c77
1 files changed, 52 insertions, 25 deletions
diff --git a/examples/cpque.c b/examples/cpque.c
index 5866f17b..502a8c7b 100644
--- a/examples/cpque.c
+++ b/examples/cpque.c
@@ -1,24 +1,40 @@
// Implements c++ example: https://en.cppreference.com/w/cpp/container/priority_queue
+// Example of dynamic compare function
+
#include <stdio.h>
#include <stdbool.h>
+#include <stc/forward.h>
+#include <stc/views.h>
-// Example of dynamic compare function
+// predeclare
+declare_cpque(ipque, int);
-static bool (*less_fn)(const int* x, const int* y);
+struct {
+ ipque Q;
+ bool (*less)(const int*, const int*);
+} typedef IPQueue;
-#define i_val int
-#define i_less less_fn
#define i_type ipque
+#define i_val int
+#define i_opt c_declared // avoid redeclaring container type
+#define i_less_functor(self, x, y) c_container_of(self, IPQueue, Q)->less(x, y) // <== This.
#include <stc/cpque.h>
-void print_queue(ipque q) {
- ipque copy = ipque_clone(q);
- while (!ipque_empty(&copy)) {
- printf("%d ", *ipque_top(&copy));
- ipque_pop(&copy);
- }
+#define print(name, q, n) do { \
+ printf("%s: \t", name); \
+ c_forrange (i, n) printf("%d ", q[i]); \
+ puts(""); \
+} while(0)
+
+void print_queue(const char* name, IPQueue q) {
+ // NB: make a copy because there is no way to traverse
+ // priority_queue's content without erasing the queue.
+ IPQueue copy = {ipque_clone(q.Q), q.less};
+
+ for (printf("%s: \t", name); !ipque_empty(&copy.Q); ipque_pop(&copy.Q))
+ printf("%d ", *ipque_top(&copy.Q));
puts("");
- ipque_drop(&copy);
+ ipque_drop(&copy.Q);
}
static bool int_less(const int* x, const int* y) { return *x < *y; }
@@ -28,18 +44,29 @@ static bool int_lambda(const int* x, const int* y) { return (*x ^ 1) < (*y ^ 1);
int main()
{
const int data[] = {1,8,5,6,3,4,0,9,7,2}, n = c_arraylen(data);
- c_auto (ipque, q, q2, q3) // init() and defered drop()
- {
- less_fn = int_less;
- c_forrange (i, n) ipque_push(&q, data[i]);
- print_queue(q);
-
- less_fn = int_greater;
- c_forrange (i, n) ipque_push(&q2, data[i]);
- print_queue(q2);
-
- less_fn = int_lambda;
- c_forrange (i, n) ipque_push(&q3, data[i]);
- print_queue(q3);
- }
+ print("data", data, n);
+
+ IPQueue q1 = {ipque_init(), int_less}; // Max priority queue
+
+ c_forrange (i, n)
+ ipque_push(&q1.Q, data[i]);
+
+ print_queue("q1", q1);
+
+ // Min priority queue
+ // std::greater<int> makes the max priority queue act as a min priority queue
+ IPQueue minq1 = {ipque_init(), int_greater};
+ c_forrange (i, n) ipque_push(&minq1.Q, data[i]);
+
+ print_queue("minq1", minq1);
+
+ // Using lambda to compare elements.
+ IPQueue q5 = {ipque_init(), int_lambda};
+
+ c_forrange (i, n)
+ ipque_push(&q5.Q, data[i]);
+
+ print_queue("q5", q5);
+
+ c_drop(ipque, &q1.Q, &minq1.Q, &q5.Q);
}