Main Content

CERT C++: CTR57-CPP

Provide a valid ordering predicate

Since R2022a

Description

Rule Definition

Provide a valid ordering predicate.1

Polyspace Implementation

The rule checker checks for Use of predicate lacking strict weak ordering

Examples

expand all

Issue

Use of predicate lacking strict weak ordering occurs when you use one of these compare types as predicates in standard template library (STL) algorithms and containers:

  • std::less_equal

  • std::greater_equal

  • std::equal_to

  • std::not_equal_to

  • std::logical_or

  • std::logical_and

For a list of standard library algorithms that expect a predicate with strict weak ordering, see Compare.

If you use a user-defined predicate function, Polyspace® does not check if the custom predicate adheres to strict weak ordering.

Risk

Algorithms and containers of the standard template library use predicates to sort and compare their elements. The predicates must adhere to strict weak ordering. That is, the predicate must adhere to these requirements:

  • Irreflexivity: For all x, comparing x to itself must always evaluate to false.

  • Assymetry: Far all x, y: if comparing x to y evaluates to true, then comparing y to x must evaluate to false.

  • Transitivity: For all x, y, z: if comparing x to y and y to z both evaluate to true, then comparing x to z must also evaluate to true.

These compare type methods violate at least one of these requirements:

  • std::less_equal

  • std::greater_equal

  • std::equal_to

  • std::not_equal_to

  • std::logical_or

  • std::logical_and

Using the preceding predicates with algorithms and containers from the standard library might result in infinite loops, erratic behavior, and bugs that are difficult to diagnose.

Fix

To resolve this defect, avoid using the preceding methods as predicates for algorithms and containers from the standard template library. Instead, use methods that adhere to strict weak ordering. For instance, use functions such as std::less or std::greater. The STL uses these functions or their equivalent operators as the default ordering predicate. Using the default predicate might be sufficient to resolve the defect.

Example — Avoid Using Predicates That Do Not Adhere to Strict Weak Ordering with STL Algorithms
#include <functional>
#include <iostream>
#include <set>
#include <map>

int main(void)
{
    // GE
    std::set<int, std::greater_equal<int>>//Noncompliant
		s1{2, 5, 8};   
    auto r = s1.equal_range(5);
    //returns 0
    std::cout << std::distance(r.first, r.second) << std::endl;

    //LE
    std::map<int, std::string, std::less_equal<int>>//Noncompliant 
		m1{{2, "AB"}, {5, "CD"}, {8, "EF"}}; 
    auto r3 = m1.equal_range(5);
    //returns 0
    std::cout << std::distance(r3.first, r3.second) << std::endl;
    
    return 0;
}

In this example, Polyspace flags the use of inappropriate predicates when declaring STL containers. For instance:

  • The predicate greater_equal does not return false when comparing the same objects, violating the irreflexivity requirement.

  • The predicate less_equal does not return false when comparing the same objects, violating the irreflexivity requirement.

Polyspace flags the use of these function as predicates when declaring containers such as std::set or std::map.

Correction — Use the Default Predicate

By default, these containers use the function std::less as the ordering predicate. Because this function adheres to strict weak ordering relation, Polyspace does not raise a violation when you declare the containers by using the default predicate.

#include <functional>
#include <iostream>
#include <set>
#include <map>

int main(void)
{
    std::set<int> s2{2, 5, 8}; //Compliant
    auto r2 = s2.equal_range(5);
    //returns 1
    std::cout << std::distance(r2.first, r2.second) << std::endl;

    
    std::map<int, std::string> m2{{2, "AB"}, {5, "CD"}, {8, "EF"}}; //Compliant
    auto r4 = m2.equal_range(5);
    //returns 1
    std::cout << std::distance(r4.first, r4.second) << std::endl;

    return 0;
}

Check Information

Group: Rule 04. Containers (CTR)

Version History

Introduced in R2022a


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.