C++确定容器是否具有 ::find()

C++ determine if a container has ::find()

本文关键字:find 是否 C++      更新时间:2023-10-16

我有一个函子,它在类型 U 的容器上运行 T 类型的元素,如下所示

template<typename T, template<typename...> class U>
class asserter 
{
public:
    asserter(U<T> &c) : container(c) { };
    void operator()(T lhs) 
    {
        CU_ASSERT(container.find(lhs) != container.end());
    };
private:
    U<T>    &container;
};

我可能会将其用作

std::set<std::string> a, c;
...
asserter<std::string, std::set> ass(c);
for_each(a.begin(), a.end(), ass);

我们暂时忽略std::includes()

如果容器是定义U::find()的容器,则此方法非常有用。如果不是,我想回到std::find().另一方面,如果可用,我宁愿使用U::find()而不是std::find()

在 C++11(或 17,如有必要(中,我可以确定U::find()是否可用(可能仅限于 STL(供您使用,如果是,请使用它,否则请使用std::find()

SFINAE 关于表达式c.find(value)是否格式正确。尾随返回类型是 C++11,无论如何在这里都不是必需的;它只是使返回类型更容易编写 - decltype(c.find(value))而不是decltype(std::declval<Container&>().find(std::declval<const T&>())).

如果表达式格式不正确,则会从重载集中删除 find_impl 的第一个重载,将第二个重载保留为唯一可行的重载。第三个参数的常用int/long/0技巧使第一个重载在两个都可行时首选。

template<class Container, class T>
auto find_impl(Container& c, const T& value, int) -> decltype(c.find(value)){
    return c.find(value);
}
template<class Container, class T>
auto find_impl(Container& c, const T& value, long) -> decltype(std::begin(c)){
    return std::find(std::begin(c), std::end(c), value);
}
template<class Container, class T>
auto find(Container& c, const T& value) -> decltype(find_impl(c, value, 0)) {
    return find_impl(c, value, 0);
}

通常的免责声明适用:这依赖于表达 SFINAE,MSVC 目前不支持该表达式;Microsoft确实计划在 MSVC 2015 的更新中添加支持。