如果类有特定的成员函数,则启用模板函数 [英] Enable template function if class has specific member function

查看:107
本文介绍了如果类有特定的成员函数,则启用模板函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了以下模板函数,它检查一个任意容器是否包含一个特定的元素:

I wrote the following template function, which checks whether an arbitary container contains a specific element:

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;
}

这适用于大多数容器。然而对于各种集合(和映射),它是次最优的,因为我们可以使用:

This works well for most containers. However for all kinds of sets (and maps) it is sub optimal since there we could use:

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;
}

显然,由于模糊性,我们不能同时使用这两个模板。现在我正在寻找一种方法使用 std :: enable_if 启用到第一个模板如果 container_t 不提供一个 count 成员函数和第二个模板。但是我不知道如何检查一个specif成员函数(使用C ++ 11)。

Obviously we can't use both templates simultaneously because of ambiguity. Now I am looking for a way to use std::enable_if to enable the to first template if container_t does not provide a count member function and the second template if it does. However I can't figure out how to check for a specif member function (using C++11).

推荐答案

+14特性,重新实现:

C++14 feature, reimplemented:

template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;

一个迷你元程序库:

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...>>;

can_apply< some_template,args ...> 继承自 true_type iff some_template< args ...> 是一个有效的表达式(在上下文中)。

can_apply< some_template, args... > inherits from true_type iff some_template<args...> is a valid expression (in the immediate context).

现在为您的问题:

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>;

has_dot_count true_type iff T.count(I)是有效的表达式。

and has_dot_count is a traits class that inherits from true_type iff T.count(I) is a valid expression.

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 );
}

使用标签分派代替SFINAE。

which uses tag dispatching instead of SFINAE.

使用 find 似乎比 .count 更好一些。事实上,在一种情况下,你应该使用 .find 另一个 find 。在这两种情况下,你应该使用 using std :: end;自动e =结束(c);

Using find seems like a better idea than .count as an aside. In fact, in one case you should use .find the other find. In both cases you should use using std::end; auto e = end(c);.

另外,MSVC 2013(我不知道2015年)这种SFINAE使用上面。他们称之为表达SFINAE。他们有自定义扩展来检测成员函数的存在。但是这是因为它们远远不符合C ++ 11标准。

As an aside, MSVC 2013 (I don't know about 2015) doesn't handle this kind of SFINAE used above. They call it "expression SFINAE". They have custom extensions to detect the existence of a member function. But that is because they are far from C++11 standard compliant.

这篇关于如果类有特定的成员函数,则启用模板函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆