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

Mic*_*len 7 c++ stl traits sfinae c++11

我有一个仿函数,它运行在类似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;
};
Run Code Online (Sandbox Code Playgroud)

我可以用它作为

std::set<std::string> a, c;
...
asserter<std::string, std::set> ass(c);
for_each(a.begin(), a.end(), ass);
Run Code Online (Sandbox Code Playgroud)

我们std::includes()暂时无视的地方.

如果容器U::find()是定义的容器,这很有用.如果不是我想回归std::find().另一方面U::find(),std::find()如果它可用,我宁愿使用它.

在C++ 11中(如果需要,可以U::find()是17)我可以确定U是否可用(可能限制为STL),如果是,请使用它,否则使用std::find()

T.C*_*.C. 7

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);
}
Run Code Online (Sandbox Code Playgroud)

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

  • 一个更有用的答案也可以解释为什么代码有效.例如,我期待一个使用SFINAE的答案.`decltype(...)`部分是C++ 17中的SFINAE技术(我认为这个lambda表达式语法是C++ 17)?另外,`int`用于强制该签名优先于`long`重载? (4认同)