Top Qs
Timeline
Chat
Perspective

Utility (C++)

From Wikipedia, the free encyclopedia

Remove ads

<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.

Remove ads

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

Summarize
Perspective

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);
}
Remove ads

std::pair

Summarize
Perspective

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);
    }
}
Remove ads

See also

References

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads