Tag Archives: C++17

Default operator== in C++

At first sight, it seems surprising that there is no compiler-generated default operator== in C++, when there is a compiler-generated default assignment operator and copy constructor. It could simply do a memberwise comparison, just as the assignment operator and copy constructor do a memberwise copy.

The reason is out of compatibility with C. In C, struct comparison is illegal, so a default operator== in C++ would have made C code that shouldn’t compile as C compile, and potentially changed its behaviour. Compatibility is the same reason why C++ does have a default assignment operator and copy constructor, which is ironic given that those are rarely wanted and are often disabled by making them private.

There is a proposal to include default comparison operators in C++17, as described here: A bit of background for the default comparison proposal — Bjarne Stroustrup.

Related

Operator overloading in C++

Finding the size of arrays and containers

Arrays

You can find the size of an array with the following template function:

template <typename T, size_t N>
size_t size(T (&)[N])
{
    return N;
}

Example:

#include <iostream>

int main()
{
    int ints[] = {1, 2, 3, 4};
    const char *pchars[] = {"a", "b", "c", "d"};
 
    std::cout << size(ints) << "\n";
    std::cout << size(pchars) << "\n";
}
4
4

Note that once an array has decayed to a pointer by being passed to a function, this will not work.

Containers

You can extend this to containers with the following two functions, which take template template parameters:

template <template<class, class> class Container, class T, class Allocator>
size_t size(const Container<T, Allocator>& cont)
{
    return cont.size();
}

template <template<class, class, class, class> class Container, class Key, class T, class Compare,
        class Allocator>
size_t size(const Container<Key, T, Compare, Allocator>& cont)
{
    return cont.size();
}

Example:

#include <iostream>
#include <vector>
#include <algorithm>
#include <map>

int main()
{
    std::vector<int> vec(10);
    std::iota(vec.begin(), vec.end(), 0);
    std::map<std::string, int> dict;
    dict["apples"] = 7;
    dict["pears"] = 9;

    std::cout << size(vec) << "\n";
    std::cout << size(dict) << "\n";
}
10
2

C++11

In C++11, you can use decltype to select the container overload, so the two template template functions can be replaced with this:

template <class Container> 
auto size(const Container& cont) -> decltype(cont.size())
{
    return cont.size();
}

C++17

C++17 has added the std::size() function, which probably uses the size_t overload for arrays, and the one using decltype for containers.