C++ 判断一个容器是否有::find()

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

我有一个仿函数,它对类型为 T 的元素类型为 U 的容器进行操作,就像这样

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() 是否对 U 可用(可能限制为 STL),如果可用,则使用它,否则使用 std::find()

SFINAE 关于表达式 c.find(value) 是否合式。 Trailing return 类型是 C++11,无论如何这里都不是必需的;它只是使 return 类型更容易编写 - 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 的更新中添加支持。