Haa*_*hii 11 c++ templates sfinae c++11
我编写了以下模板函数,它检查仲裁容器是否包含特定元素:
template<template<class, class...> class container_t, class item_t, class... rest_t>
bool contains(const container_t<item_t, rest_t...> &_container, const item_t &_item) {
for(const item_t &otherItem : _container) {
if(otherItem == _item) { return true; }
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
这适用于大多数容器.然而,对于所有类型的集合(和地图),它是次优的,因为我们可以使用:
template<template<class, class...> class set_t, class item_t, class... rest_t>
bool contains(const set_t<item_t, rest_t...> &_set, const item_t &_item) {
return _set.count(_item) > 0;
}
Run Code Online (Sandbox Code Playgroud)
显然,由于含糊不清,我们不能同时使用这两个模板.现在我正在寻找一种方法,用于std::enable_if启用第一个模板,如果container_t不提供count成员函数,第二个模板,如果它没有.但是我无法弄清楚如何检查特定成员函数(使用C++ 11).
Yak*_*ont 15
C++ 14功能,重新实现:
template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;
Run Code Online (Sandbox Code Playgroud)
一个迷你元编程库:
template<class...>struct types{using type=types;};
namespace details {
template<template<class...>class Z, class types, class=void>
struct can_apply : std::false_type {};
template<template<class...>class Z, class...Ts>
struct can_apply< Z, types<Ts...>, void_t< Z<Ts...> > >:
std::true_type
{};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z,types<Ts...>>;
Run Code Online (Sandbox Code Playgroud)
can_apply< some_template, args... >继承自true_typeiff some_template<args...>是一个有效的表达式(在直接上下文中).
现在为您的问题:
template<class T, class I>
using dot_count_type = decltype( std::declval<T>().count(std::declval<I>()) );
template<class T, class I>
using has_dot_count = can_apply<dot_count_type, T, I>;
Run Code Online (Sandbox Code Playgroud)
并且has_dot_count是一个traits类,它继承自true_typeiff T.count(I)是一个有效的表达式.
namespace details {
template<class C, class I>
bool contains(std::false_type, C const& c, I const& i) {
for(auto&& x:c) {
if(x == i) { return true; }
}
return false;
}
template<class C, class I>
bool contains(std::true_type, C const& c, I const& i) {
return c.count(i) != 0;
}
}
template<class C, class I>
bool contains( C const& c, I const& i ) {
return details::contains( has_dot_count<C const&,I const&>{}, c, i );
}
Run Code Online (Sandbox Code Playgroud)
它使用标签调度而不是SFINAE.
使用find似乎比一个更好的想法.count.事实上,在一种情况下,你应该使用.find另一种情况find.在这两种情况下你都应该使用using std::end; auto e = end(c);.
另外,MSVC 2013(我不知道2015年)不处理上面使用的这种SFINAE.他们称之为"表达SFINAE".他们有自定义扩展来检测成员函数的存在.但那是因为它们远不符合C++ 11标准.