Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specialization of 'template<class _Tp> struct std::less' in different namespace

Tags:

c++

I am specializing the 'less' (predicate) for a data type.

The code looks like this:

template<> struct std::less<DateTimeKey> {    bool operator()(const DateTimeKey& k1, const DateTimeKey& k2) const    {       // Some code ...    } }; 

When compiling (g++ 4.4.1 on Ubuntu 9.10), I get the error:

Specialization of 'template struct std::less' in different namespace

I did some research and found that there was a 'workaround' which involved wrapping the specialization in a std namespace - i.e. changing the code to:

namespace std { template<> struct less<DateTimeKey> {    bool operator()(const DateTimeKey& k1, const DateTimeKey& k2) const    {       // Some code ...    } }; } 

which indeed, shuts the compiler up. However, that solution was from a post 5 years old (By the 'great' Victor Bazarof no less [pun unintended]). Is this fix still the way to go, or is there a better way of resolving this, or is the "old way" still valid?

like image 829
Stick it to THE MAN Avatar asked Feb 17 '10 16:02

Stick it to THE MAN


2 Answers

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

[lib.reserved.names]/1

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

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

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

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

like image 39
David Rodríguez - dribeas Avatar answered Sep 27 '22 21:09

David Rodríguez - dribeas


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

like image 94
JonM Avatar answered Sep 27 '22 20:09

JonM