[ACCEPTED]-Specialization of 'template<class _Tp> struct std::less' in different namespace-c++

Accepted answer
Score: 30

This is still the way to do it. Unfortunately 4 you cannot declare or define functions within 3 a namespace like you would do with a class: you 2 need to actually wrap them in a namespace 1 block.

Score: 26

If you need to specialize a standard algorithm, you 32 can do so in the std namespace. It is the 31 only thing that you are allowed to do inside 30 that namespace according to the standard.


It 29 is undefined for a C++ program to add 28 declarations or definitions to namespace 27 std or namespaces within namespace std 26 unless otherwise specified. A program 25 may add template specializations for any 24 standard library template to namespace 23 std. Such a specialization (complete or partial) of 22 a standard library template results in 21 undefined behavior unless the declaration 20 depends on a user-defined name of external 19 linkage and unless the specialization 18 meets the standard library requirements 17 for the original template

Now, the question 16 is whether you actually want to specialize 15 std::less. Note that std::less will call the comparison operator 14 defined for your type, so you can provide 13 that operation instead of specializing the 12 template.

The problem with specializing std::less for 11 your particular type is that it will cause 10 confusion if you provide a different operation 9 than the one performed by operator< for your type. If they perform the same operation, just leave the default 8 std::less definition without specialization.

If you 7 do not want to provide the comparison operator, but 6 still want to use the type in associative 5 containers or with algorithms that require 4 a comparator, you can provide an external 3 comparison functor by other name that will 2 not confuse other readers (and yourself 1 somewhere in the future).

Score: 4

Why are you even doing this?

std::less exists for 7 two purposes only:

  1. to give a name to operator <, allowing it to be passed as a functor
  2. to explicitly allow comparing two pointers that aren't in the same array (which is technically illegal if done with raw pointers)

There's no reason for 6 a user to overload it - either overload 5 operator< or use a custom comparator function.

There 4 are std algorithms that can be sensibly 3 specialized - std::swap is a good example - and to 2 do so you do need to declare the specialization 1 inside namespace std.

Score: 2

Even though the question has been answered 17 by others with answers on how to specialize 16 std::less (by wrap them in a namespace block) and 15 the right way to do it ( to overload operator <).

However, C++ now 14 allows (in C++11) to speciliaze the way you did 13 in your first example.

An explicit specialization 12 shall be declared in a namespace enclosing 11 the specialized template. An explicit specialization 10 whose declarator-id is not qualified shall 9 be declared in the nearest enclosing namespace 8 of the template, or, if the namespace is 7 inline (7.3.1), any namespace from its enclosing 6 namespace set. Such a declaration may also 5 be a definition. If the declaration is not 4 a definition, the specialization may be 3 defined later (

I tried the following 2 code with g++ (8.3.0) on my Ubuntu machine.

#include <iostream>

#include <map>
#include <string>
#include <algorithm>

class myType {

    myType(int in): i_(in) { }

    int i_;

template <>
struct std::less<myType>  {
    bool operator()(const myType& a, const myType& b) const
        return a.i_ < b.i_;

int main(int argc, char *argv[])
    std::map<myType, std::string> vector = { { 1, "1"}, { 2, "2"}, { 3, "3"}, { 0, "0" } };

    for (auto& i: vector)
        std::cout << i.first.i_ << std::endl;
    return 0;

The above code 1 was compiled with

g++ --std=c++11 compare.cpp -Wall 
Score: 1

The less functor doesn't have to be in std namespace. So

struct A
    A(int _v=0):v(_v){}
    int v;

template<>  struct less<A>
    bool operator()(const A& k1, const A& k2) const
        return k1.v < k2.v;

std::map<A,int> m;
m[A(1)] = 1;
m[A(2)] = 2;

Works 4 as expected. (Calls the functor you just 3 created).

I guess you already know, but you 2 can just write your own operator<(k1,k2), which 1 is what default less functor looks for.

bool operator<(const DateTimeKey & k1, const DateTimeKey & k2)
//your code...

More Related questions