Enable template function if class has specific member function

后端 未结 1 2014
野的像风
野的像风 2020-12-31 09:14

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

template          


        
相关标签:
1条回答
  • 2020-12-31 09:48

    C++14 feature, reimplemented:

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

    A mini metaprogramming library:

    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... > inherits from true_type iff some_template<args...> is a valid expression (in the immediate context).

    Now for your problem:

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

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

    which uses tag dispatching instead of SFINAE.

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

    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.

    0 讨论(0)
提交回复
热议问题