Abruzzo Forte e Gentile
Abruzzo Forte e Gentile

Reputation: 14869

STL algorithms on heterogeneous collections by using specialized functions

I would like to use algorithm std::include to work with heterogeneous STL collections. In my example I would like to check if a std::vector of integer is included in a std::map.

I would like to solve this problem by using a simple templated function; the reason for this is because I would like to use the C++ template argument deduction to let deduce when first argument of the comparer function is a std::pair vs an int and the other way around ( std::include behind the scenes calls Comp(a,b) and Comp(b,a) ).

Below my code I would like to run

    typedef std::map<int,std::string> dict;
    typedef std::vector<int> vect;

    int data[]={1,2,3,4};
    vect l(data,data+4);
    dict h;
    h.insert(dict::value_type(0,"ciccio"));
    h.insert(dict::value_type(1,"ciccio"));                  
    std::includes( h.begin(),h.end()
        , l.begin(), l.end(), is_my_less );

I tried the following below but it doesn't compile and say partial specialization is not allowed but also unresolved overloaded function type that makes me think that I am doing something wrong with my function. Do you know is that is possible by using strictly a templated function?

    template<class T1,class T2,class T3>
    bool is_less_than_pair( const T1&a ,const T2& b ){
        return false;
    };

    template<class T1,class T>
    bool is_less_than_pair<
        T1
        , std::pair<T1,T>
        , T >( const T1&a, const std::pair<T1,T>& b ){
        return a<b.first;
    }

    template<class T1, class T>
    bool is_less_than_pair< 
        std::pair<T1,T>
        ,T1
        , T >( const std::pair<T1,T>& a, const T1& b ){
        return a.first<b;
    }

Now based on the fact that function templates cannot be partially specialized I tried function overloading like below but it didn't work out and gcc tells me unresolved overloaded function type again. What is the best I can do?

      template<class T1,class T2>
      bool is_less_than_pair( const std::pair<T1,T2>& a ,const T1& b ){
        return a.first<b;
      };
      template<class T1,class T2>
      bool is_less_than_pair( const T1& a ,const std::pair<T1,T2>& b ){
        return b.first<a;
      };

Upvotes: 0

Views: 210

Answers (1)

Dave S
Dave S

Reputation: 21123

If you're restricted to functions, no. You can't use an overloaded function, because it won't be able to select the proper overload when passing it to the STL algorithm. And you can't partially specialize a function template.

It can be done with a function object, by providing all of the overloads. In effect, you'll pass all of the overloads to the STL algorithm, and then it will choose the appropriate overload as it's called. Note, due to the fact that the map's values are std::pair<const int, string>&, use of the same T1 in both sides of the mixed-mode operators will not work, since the vector's iterators are turning int&, where the map's are using a constant.

struct my_less_than
{
   template <typename T1>
   bool operator()(const T1& lhs, const T1& rhs) const
   {
      return lhs < rhs;
   }

   template <typename T1, typename T2, typename T3>
   bool operator()(const T1& lhs, const std::pair<T2, T3>& rhs) const
   {
      return lhs < rhs.first;
   }

   template <typename T1, typename T2, typename T3 >
   bool operator()(const std::pair<T1, T2>& lhs, const T3& rhs) const
   {
      return lhs.first < rhs;
   }

   template <typename T1, typename T2, typename T3>
   bool operator()(const std::pair<T1, T2>& lhs, const std::pair<T1, T3>& rhs) const
   {
      return lhs.first < rhs.first;
   }
};

Usage:

   std::includes( h.begin(),h.end()
        , l.begin(), l.end(), my_less_than() );

Edit: Example http://ideone.com/JFIoy

Upvotes: 4

Related Questions