Why does std::map code compile when operator < is not defined for its data type?

Viewed 78

I've learned that passing a user-defined type to a std::map (as well as many other STL data structures) requires the definition of the operator <.

Doesn't that mean, however, that the compiler would be able to verify whether declarations of a std::map are correct at compile-time? The below code, which declares a std::map with a user-defined data-type that has no < operator, still compiles. Can somebody please tell me why this is true?

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

using namespace std;

struct Test{
    int a;
    string b;
};

int main()
{
    map <Test, int> M; // shouldn't this line cause a compilation error, as operator < is not defined                  
                       // for class Test?

    return 0;
}

1 Answers

In C++(footnote) templates don't have static constraints on their type-parameters (unlike C#'s where constraints). Instead the correctness of C++ template parameter arguments is only determinable when each template member is instantiated by the compiler (compile-time type instantiation, not runtime object instantiation). Your code only uses map's parameterless constructor which does not make use of key_type's overloaded < operator.

If you have experience with the npm JavaScript ecosystem, think of it as extreme tree-shaking: library functions that aren't used aren't compiled, and if they aren't compiled then they aren't subject to compiler errors. This Zero-overhead Principle of the C++ language is also known as "You don't pay for what you don't use" (though don't confuse this with "zero-cost abstractions" which is something else).

1: C++20 has added template parameter constraints, but I imagine we won't see that in STL types for long while as it would be a major breaking change : https://en.cppreference.com/w/cpp/language/constraints

Related