首页 > 解决方案 > 重载 STL 函数

问题描述

我有这样的代码:

   set<array<int, 3>> s;
   int ar[3] = {1,2,3};
   s.insert(ar);
   auto it = s.find(ar);

以及 IDE 的消息no instance of overloaded function insert/find。如果我使用std::array它是可以的,::insert并且::find以同样的方式工作。但是,如果我想使用这些 C 数组T[N]或使用 in set 查找函数,std::array如果三个元素中的两个相等,应该返回迭代器。或者set::insert如果它是存在的排列,则不会插入新数组,我的意思是s.insert({1,2,3})- 已经添加s.insert({3,2,1})- 返回迭代器 on {1,2,3}

问题是如何重载 STD 函数?不是在这段代码中,而是在一般情况下?欢迎任何链接或真实代码示例。对于有经验的程序员来说,这可能是一个非常简单的问题)但是有很多运算符重载的例子,但对于 STL 却没有。谢谢。

标签: c++stloverloading

解决方案


您不能在类定义之外为类的成员函数声明额外的重载。该语言不为其提供语法。由于您无法修改标准库头文件中的类定义,因此您也无法向它们添加额外的重载。


命名空间中的自由函数std可能不会被重载。它有语法(与任何自由函数重载的工作方式相同),但这样做会导致未定义的行为,因为它在标准中被明确禁止,请参阅[namespace.std]/1


通常(有例外)允许的是为命名空间中的实体定义模板std特化,但前提是特化依赖于用户定义的类型,而不是成员函数、成员函数模板或成员类模板。请参阅上面链接的其余引用和以下段落。

使用命名空间内的特化的一个常见示例std是用作std::hash无序关联容器中的哈希函数:

struct my_type {
    //...
};

namespace std {
    template<>
    struct hash<my_type> {
        auto operator()(my_type const& x) const noexcept {
            //...
        }
    };
}

但即使是类似的东西如果my_type被替换为int*,int[3]std::array<int, 3>类似的东西也是不允许的,因为不依赖于用户声明的类型。


如果你想std::array从一个内置数组中创建一个,你将能够std::to_array在 C++20 中使用:

set<array<int, 3>> s;

int ar[3] = {1,2,3};

s.insert(std::to_array(ar));

auto it = s.find(std::to_array(ar));

在 C++20 之前,您可能拥有可用的函数std::experimental::to_array#include<experimental/array>或者您可以自己定义它(来自cppreference.com;需要#include<type_traits>和):#include<utility>#include<cstddef>

namespace detail {

template <class T, std::size_t N, std::size_t... I>
constexpr std::array<std::remove_cv_t<T>, N>
    to_array_impl(T (&a)[N], std::index_sequence<I...>)
{
    return { {a[I]...} };
}

}

template <class T, std::size_t N>
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N])
{
    return detail::to_array_impl(a, std::make_index_sequence<N>{});
}

推荐阅读