Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如果类具有特定的成员函数,则启用模板函数_C++_Templates_C++11_Sfinae - Fatal编程技术网

C++ 如果类具有特定的成员函数,则启用模板函数

C++ 如果类具有特定的成员函数,则启用模板函数,c++,templates,c++11,sfinae,C++,Templates,C++11,Sfinae,我编写了以下模板函数,用于检查任意容器是否包含特定元素: 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 &a

我编写了以下模板函数,用于检查任意容器是否包含特定元素:

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;
}
模板
bool包含(常量容器和常量容器、常量项和常量项){
对于(常量项和其他项:\容器){
if(otherItem==\u item){return true;}
}
返回false;
}
这适用于大多数容器。但是,对于所有类型的集合(和贴图),它都是次优的,因为我们可以使用:

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;
}
模板
bool包含(常数集和常数集、常数项和常数项){
返回设置计数(_项)>0;
}

显然,由于模棱两可,我们不能同时使用这两个模板。现在,我正在寻找一种使用
std::enable_if
的方法,如果
container\t
未提供
count
成员函数,则启用to第一个模板,如果提供了第二个模板,则启用第二个模板。但是,我不知道如何检查指定的成员函数(使用C++11)。

C++14功能,重新实现:

template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;
has\u dot\u count
是从
true\u type
iff
T继承的traits类。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 );
}
名称空间详细信息{
模板
bool包含(std::false_类型、C常量和C、I常量和I){
用于(自动和x:c){
如果(x==i){返回true;}
}
返回false;
}
模板
布尔包含(标准::真_类型、C常量和C、I常量和I){
返回c.count(i)!=0;
}
}
模板
布尔包含(C常量和C,I常量和I){
返回详细信息::包含(has_dot_count{},c,i);
}
它使用标记分派而不是SFINAE

使用
find
似乎比
.count
作为旁白更好。事实上,在一种情况下,您应该使用
.find
另一种
find
。在这两种情况下,您都应该使用std::end;自动e=结束(c)


顺便说一句,MSVC 2013(我不知道2015年的情况)没有处理上面使用的这种SFINAE。他们称之为“表达SFINAE”。它们具有自定义扩展以检测成员函数的存在。但这是因为它们远远不符合C++11标准。

如果您愿意将boost作为一个依赖项添加,那么在
boost\u TTI\u has\u MEMBER\u函数中就有您想要的功能了。
macro您完全确定要这样做吗?在标准库中,它们让您准确地说明在进行线性搜索和使用更高效的机制时,您要使用哪个
find
表单来明确说明。如果你真的想这么做,请务必使用
find
而不是
count
,这只是为了避免过早的悲观情绪。@SimonGibbons:谢谢,这看起来正是我需要的。但是我现在不想依赖boost。@MarkB:据我所知,
std::find
也会根据我们是否有一个有序的容器使用不同的算法,不是吗?至少写下,复杂性最多是线性的,即对于合适的容器可以小于线性。但是,如果我错了,请纠正我。@Haatschii标准只是说“最多最后一次第一次比较”,因此假设它对所有容器类型都是线性的。与2015(至少预览版)有趣的方法相比。对我来说效果很好(GCC 4.8)。非常感谢你。
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>;
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 );
}