Utility (C++)

From Wikipedia, the free encyclopedia

<utility> is a header file in the C++ Standard Library. This file has two key components:

  • std::rel_ops, a namespace containing set of templates which define default behavior for the relational operators !=, >, <=, and >= between objects of the same type, based on user-defined operators == and <.
  • std::pair<T, U>, a container template which holds two member objects (first and second) of arbitrary type(s). Additionally, the header defines default relational operators for pairs which have both types in common.

.mw-parser-output .monospaced{font-family:monospace,monospace}std::rel_ops

GCC's implementation declares the std::rel_ops namespace in a manner similar to the following:[1]

namespace std::rel_ops {
	template <typename T> 
    inline bool operator!=(const T& x, const T& y) {
        return !(x == y);
    }

	template <typename T>
    inline bool operator>(const T& x, const T& y) {
        return y < x;
    }

	template <typename T>
    inline bool operator<=(const T& x, const T& y) {
        return !(y < x);
    }

	template <typename T>
    inline bool operator>=(const T& x, const T& y) {
        return !(x < y);
    }
}

Consider the following declaration of class BuildingLocation, which defines equality and less-than operators for comparison against other objects of the same type:

import std;

using namespace std::rel_ops;

class BuildingLocation {
    unsigned int building;
    unsigned int room;
public:
    bool operator==(const BuildingLocation& other) const {
        return (building == other.building) && (room == other.room);
    }

    bool operator<(const BuildingLocation& other) const {
        return (building < other.building)
            || (!(other.building < building) && (room < other.room));
    }
};

void f1(const BuildingLocation& a1, const BuildingLocation& a2) {
    bool equal = a1 == a2; // uses == defined within class A
    bool not_equal = a1 != a2; // error: no match for ‘operator!=’ in ‘a1 != a2’
    bool less = a1 < a2; // uses < defined within class A
    bool greater = a1 > a2; // error: no match for ‘operator >’ in ‘a1  > a2’
    bool less_equal = a1 <= a2; // error: no match for ‘operator<=’ in ‘a1 <= a2’
    bool greater_equal = a1 >= a2; // error: no match for ‘operator>=’ in ‘a1 >= a2’
}

By invoking the std::rel_ops templates, one can assign a default meaning to the remaining relational operators. However, if a similar type-specific (i.e. non-template) operator exists in the current scope, even outside the class definition, the compiler will prefer it instead.

// (continued from above)

// below operator supersedes rel_ops
bool operator>=(const BuildingLocation& a1, const BuildingLocation& a2) {
    do_something_else(); // perform some distinguishing side-effect
    return !(a1 < a2); // but otherwise use same procedure as rel_ops
};

void f2(const BuildingLocation& a1, const BuildingLocation& a2) {
    bool equal = a1 == a2; // uses operator == defined within class A
    bool not_equal = a1 != a2; // uses !(a1 == a2) per rel_ops
    bool less = a1 < a2; // uses operator  < defined within class A
    bool greater = a1 > a2; // uses (a2 < a1) per rel_ops
    bool less_equal = a1 <= a2; // uses !(a2 < a1) per rel_ops
    bool greater_equal = a1 >= a2; // uses global operator >= defined above
}

One could of course declare the following in tandem with rel_ops, allowing the derivation of all relational operators from <:

template <typename T>
inline bool operator==(const T& x, const T& y) {
    return !(x < y || y < x);
}

std::pair

std::pair<T1, T2> is a struct that encapsulates two objects of two types. An object declared, for example, as std::pair<int, float> will contain two members, int first; and float second;, plus three constructor functions.

The first (default) constructor initializes both members with the default values 0 and 0.0, whereas the second one accepts one parameter of each type. The third is a template copy-constructor which will accept any std::pair<U1, U2>, provided the types U1 and U2 are capable of implicit conversion to int and float respectively.

The implementation of std::pair<T, U> looks roughly similar to the following:[2]

namespace std {
    template <typename T1, typename T2> 
    struct pair {
        using first_type = T1;
        using second_type = T2;
        T1 first;
        T2 second;
        pair(): 
            first(), second() {}

        pair(const T1& a, const T2& b):
            first(a), second(b) {}

        template <typename U1, typename U2>
        pair(const pair<U1, U2>& p):
            first(p.first), second(p.second) {}
    };
}

Additionally this header defines all six relational operators for pair instances with both types in common. These define a strict weak ordering for objects of type std::pair<_T1, _T2>, based on the first elements and then upon the second elements only when the first ones are equal.

namespace std {
    template <typename T1, typename T2>
    inline bool operator==(const pair<T1, T2>& x, const pair<T1, T2>& y) {
        return x.first == y.first && x.second == y.second;
    }

    template <typename T1, typename T2>
    inline bool operator<(const pair<T1, T2>& x, const pair<T1, T2>& y) {
        return x.first < y.first || (!(y.first < x.first) && x.second < y.second);
    }

    template <typename T1, typename T2>
    inline bool operator!=(const pair<T1, T2>& x, const pair<T1, T2>& y) {
        return !(x == y);
    }

    template <typename T1, typename T2>
    inline bool operator>(const pair<T1, T2>& x, const pair<T1, T2>& y) {
        return y < x;
    }

    template <typename T1, typename T2>
    inline bool operator<=(const pair<T1, T2>& x, const pair<T1, T2>& y) {
        return !(y < x);
    }

    template <typename T1, typename T2>
    inline bool operator>=(const pair<T1, T2>& x, const pair<T1, T2>& y) {
        return !(x < y);
    }
}

Additionally the header contains a template-function make_pair() which deduces its return type based on parameters:

namespace std {
    // continued from above
    template <typename T1, typename T2>
    inline pair<T1, T2> make_pair(T1 x, T2 y) {
        return pair<T1, T2>(x,y);
    }
}

See also

References

Related Articles

Wikiwand AI