@@ -40,4 +40,70 @@ void test_standard_library_predicates() {
4040 std::vector<std::int32_t > l1 = {1 , 2 , 3 , 4 , 5 };
4141 // TODO: implement stubs for greater comparator.
4242 // std::sort(l1.begin(), l1.end(), std::greater<std::int32_t>()); // COMPLIANT
43+ }
44+
45+ // =============================================================================
46+ // Test cases for Rule 28.3.1#PredicateWithPersistentSideEffects
47+ // This query checks that predicates do not have persistent (global/static)
48+ // side effects.
49+ // =============================================================================
50+
51+ // Non-compliant: free function predicate modifying a static local variable
52+ bool cmp_with_static (std::int32_t l1, std::int32_t l2) {
53+ static std::int32_t g_count = 0 ;
54+ ++g_count; // NON_COMPLIANT
55+ return l1 < l2;
56+ }
57+
58+ void test_predicate_fn_static_local () {
59+ std::vector<std::int32_t > l1 = {5 , 2 , 8 , 1 , 9 };
60+ std::sort (l1.begin (), l1.end (), cmp_with_static); // NON_COMPLIANT
61+ }
62+
63+ // Non-compliant: free function predicate modifying a global variable
64+ std::int32_t g_predicate_call_count = 0 ;
65+
66+ bool cmp_with_global (std::int32_t l1, std::int32_t l2) {
67+ ++g_predicate_call_count; // NON_COMPLIANT
68+ return l1 < l2;
69+ }
70+
71+ void test_predicate_fn_global () {
72+ std::vector<std::int32_t > l1 = {5 , 2 , 8 , 1 , 9 };
73+ std::sort (l1.begin (), l1.end (), cmp_with_global); // NON_COMPLIANT
74+ }
75+
76+ // Non-compliant: function object whose operator() modifies a global variable
77+ struct F3_SideEffect {
78+ bool operator ()(std::int32_t l1, std::int32_t l2) const {
79+ ++g_predicate_call_count; // NON_COMPLIANT
80+ return l1 < l2;
81+ }
82+ };
83+
84+ void test_function_object_with_global_side_effect () {
85+ std::vector<std::int32_t > l1 = {5 , 2 , 8 , 1 , 9 };
86+ std::sort (l1.begin (), l1.end (), F3_SideEffect{}); // NON_COMPLIANT
87+ }
88+
89+ // Compliant: free function predicate with no side effects
90+ bool cmp_pure (std::int32_t l1, std::int32_t l2) { // COMPLIANT
91+ return l1 < l2;
92+ }
93+
94+ void test_predicate_fn_pure () {
95+ std::vector<std::int32_t > l1 = {5 , 2 , 8 , 1 , 9 };
96+ std::sort (l1.begin (), l1.end (), cmp_pure); // COMPLIANT
97+ }
98+
99+ // Compliant: function object with const operator() and no side effects
100+ struct F4_Pure {
101+ bool operator ()(std::int32_t l1, std::int32_t l2) const { // COMPLIANT
102+ return l1 < l2;
103+ }
104+ };
105+
106+ void test_function_object_pure () {
107+ std::vector<std::int32_t > l1 = {5 , 2 , 8 , 1 , 9 };
108+ std::sort (l1.begin (), l1.end (), F4_Pure{}); // COMPLIANT
43109}
0 commit comments