我有一个仿函数,它对类型为U
的{{1}}类型的容器进行操作
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()
。
在C ++ 11中(如果需要,可以是17)我可以确定U是否可用std::find()
(可能限制为STL),如果是,请使用它,否则使用U::find()
?
答案 0 :(得分: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);
}
通常的免责声明适用:这取决于表达SFINAE,MSVC目前不支持; Microsoft确实计划在MSVC 2015的更新中添加支持。