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

C++ C++;确定容器是否具有::find(),c++,c++11,stl,traits,sfinae,C++,C++11,Stl,Traits,Sfinae,我有一个函子,它在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) != containe

我有一个函子,它在
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;
};
模板
类断言器
{
公众:
资产(U&c):容器(c){};
void运算符()(T lhs)
{
CU_ASSERT(container.find(lhs)!=container.end());
};
私人:
U&container;
};
我可以用它作为

std::set<std::string> a, c;
...
asserter<std::string, std::set> ass(c);
for_each(a.begin(), a.end(), ass);
std::集合a、c;
...
资产评估师助理(c);
对于每个(a.begin()、a.end()、ass);
我们暂时忽略了std::includes()

如果容器是定义了
U::find()
的容器,那么这种方法非常有效。如果不是,我想回到
std::find()
。另一方面,如果可用,我宁愿使用
U::find()
而不是
std::find()


在C++11(或17,如果必要的话)中,我可以确定U是否有可用的
U::find()
(可能限制到STL),如果有,使用它,否则使用
std::find()

s检查表达式
c.find(value)
的格式是否正确。尾随返回类型是C++11,在这里并不重要;它只是使返回类型更容易编写-
decltype(c.find(value))
,而不是
decltype(std::declval().find(std::declval())

如果表达式的格式不正确,则从重载集中删除
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);
}
模板
自动查找(Container&c,const&value,int)->decltype(c.find(value)){
返回c.find(值);
}
模板
自动查找(容器和c、常量和值、长)->decltype(标准::开始(c)){
返回std::find(std::begin(c)、std::end(c)、value);
}
模板
自动查找(容器和c、常量和值)->decltype(查找(c、值、0)){
返回find_impl(c,value,0);
}

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

一个更有用的答案也将解释代码工作的原因。例如,我希望得到一个使用SFINAE的答案。
decltype(…)
部分是C++17中的SFINAE技术吗(我认为这个lambda表达式语法是C++17)?另外,
int
是否用于强制该签名优先于
long
重载?我担心
std::find
表示相等,而
std::set::find
etc表示相等。我们需要考虑这一点吗?NICYC我知道理论上它们是不同的,但是现实世界中的情况有多频繁呢?我认为
set
map
(以及他们的
multi
近亲)是唯一重要的,
unordered\u set
unordered\u map
应该使用相等的方法。@JamesAdkison这是SFINAE,它从C++11开始工作。这里没有lambda,但这也是C++11.TIL重载选择的int/long技巧。虽然我个人会使用两个基类和派生标记类来更清楚地表达层次结构(如迭代器标记)