代码之家  ›  专栏  ›  技术社区  ›  intrigued_66

C++为自定义(模板)类重载std::abs?复制

  •  0
  • intrigued_66  · 技术社区  · 3 年前

    写我自己的数字类。过载 std::numeric_limit::max() 好的然而,我正试图超载 std::abs() 但是编译器不喜欢我的尝试。我试过了:

    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;
        }
    }
    

    但是,编译器找不到重载:

    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)
    

    调用它的代码:

    MyType<10> mt;
    MyType<10> abs = std::abs(mt);
    
    2 回复  |  直到 3 年前
        1
  •  6
  •   NathanOliver    3 年前

    不允许将重载添加到 std 命名空间。在C++20之前,您可以专门化函数,但这不会有帮助,因为您的类型是模板化的,并且不允许函数的部分模板专门化。

    通常,您所做的是在代码中导入要使用的函数,然后对所述函数执行非限定调用,如

    template <typename T>
    auto some_func(const T& foo)
    {
        using std::abs;
        return abs(foo);
    }
    

    现在如果 T 是一种类型 std::abs 可以处理,则将使用它。如果不是,但它是一个具有自己的abs函数的类型,要么在全局空间中声明,要么在该类型自己的命名空间中声明,那么它将使用不合格的查找规则来找到。

        2
  •  4
  •   user17732522    3 年前

    将函数或函数模板声明添加到 std 不允许使用命名空间。

    您应该将重载放入声明自定义类型的命名空间中,然后使用非限定名称调用函数,这样依赖于参数的查找就可以找到重载。

    如果您在呼叫现场不确定 std::abs 或者应该调用您的过载,然后执行 using std::abs; 在调用之前的调用作用域中。

    自定义 abs 然而,like that并不是为了例如。 swap 并且您不能假设库用户会以上述形式调用它。