C++ overload std::abs for custom (template) class?

Advertisements

Wrote my own numeric class. Overloaded std::numeric_limit::max() fine. However, I’m trying to overload std::abs() but the compiler doesn’t like my attempt. I’ve tried this:

namespace std 
{
    template<uint8_t T> 
    MyType<T> abs(const MyType<T>& mt)
    {
        MyType<T> copy = mt;
        copy.val = std::abs(md.val);
        return copy;
    }
}

However, the compiler isn’t finding the overload:

error: no matching function for call to ‘abs(const MyType<10>&)’
/usr/include/c++/11/bits/std_abs.h:56:3: note: candidate: ‘long int std::abs(long int)’
   56 |   abs(long __i) { return __builtin_labs(__i); }
      |   ^~~
/usr/include/c++/11/bits/std_abs.h:56:12: note:   no known conversion for argument 1 from ‘const MyType<10>’ to ‘long int’
   56 |   abs(long __i) { return __builtin_labs(__i); }
      |       ~~~~~^~~
/usr/include/c++/11/bits/std_abs.h:61:3: note: candidate: ‘long long int std::abs(long long int)’
   61 |   abs(long long __x) { return __builtin_llabs (__x); }
      |   ^~~
/usr/include/c++/11/bits/std_abs.h:61:17: note:   no known conversion for argument 1 from ‘const MyType<10>’ to ‘long long int’
   61 |   abs(long long __x) { return __builtin_llabs (__x); }
      |       ~~~~~~~~~~^~~
/usr/include/c++/11/bits/std_abs.h:71:3: note: candidate: ‘constexpr double std::abs(double)’
   71 |   abs(double __x)
      |   ^~~
/usr/include/c++/11/bits/std_abs.h:71:14: note:   no known conversion for argument 1 from ‘const MyType<10>’ to ‘double’
   71 |   abs(double __x)
      |       ~~~~~~~^~~
/usr/include/c++/11/bits/std_abs.h:75:3: note: candidate: ‘constexpr float std::abs(float)’
   75 |   abs(float __x)
      |   ^~~
/usr/include/c++/11/bits/std_abs.h:75:13: note:   no known conversion for argument 1 from ‘const MyType<10>’ to ‘float’
   75 |   abs(float __x)
      |       ~~~~~~^~~
/usr/include/c++/11/bits/std_abs.h:79:3: note: candidate: ‘constexpr long double std::abs(long double)’
   79 |   abs(long double __x)
      |   ^~~
/usr/include/c++/11/bits/std_abs.h:79:19: note:   no known conversion for argument 1 from ‘const MyType<10>’ to ‘long double’
   79 |   abs(long double __x)

Code calling it:

MyType<10> mt;
MyType<10> abs = std::abs(mt);

>Solution :

Adding function or function template declarations into the std namespace is not allowed.

You should put the overloads into the namespace where your custom type is declared and then call the function with an unqualified name, so that argument-dependent lookup can find your overload.

If you are not sure at the call site whether std::abs or your overload should be called, then do using std::abs; in the calling scope before the call.

Customizing abs like that is however not intended like it is for e.g. swap and you cannot assume that a library user will call it in the above form.

Leave a ReplyCancel reply