Function that takes an STL iterator over ANY container of a elements of a specific type

前端 未结 5 1969
刺人心
刺人心 2021-02-12 19:12

How would I define a function that takes as input an iterator over any type of STL container, but only to those of a specific templated type. For example:

Any iterator o

相关标签:
5条回答
  • 2021-02-12 19:27

    Well i would use a simple typedef in the case that you only need one container-type at the time (if i understood your usecase correctly this is the case)

    template <class T>
    class ContainerIterator
    {
      Container();
      public:
        typedef std::list<T>::iterator type;
    }
    
    //usage:
    void function(ContainerIterator<YourType>::type begin, ContainerIterator<YourType>::type end)
    {
      //...
    }
    

    to switch the container later on, simply change the container type in the typedef.

    0 讨论(0)
  • 2021-02-12 19:30

    Another way with templates is to trigger a static assertion if the condition is not met.

    #include <iterator>
    #include <boost/type_traits/is_same.hpp>    
    #include <boost/static_assert.hpp>
    
    template <class Type, class Iter>
    void foo(Iter from, Iter to)
    {
        BOOST_STATIC_ASSERT((boost::is_same<typename std::iterator_traits<Iter>::value_type, Type>::value));
        //...
    }
    
    int main()
    {
        int arr[10];
        foo<int>(arr, arr + 10);    //OK
        foo<double>(arr, arr + 10); //triggers static assertion
    }
    

    If you want to do away with templates, then it is also possible to write an "any_iterator" using type erasure. For example, like this on: http://stlab.adobe.com/classadobe_1_1any__iterator.html

    0 讨论(0)
  • 2021-02-12 19:32

    In addition to the existing answers relying on SFINAE, a simpler approximation would be to simply define the function to take an arbitrary template type as the iterator:

    template <typename Iter>
    void function(Iter first, Iter last){
      Unit* val = *first;
    }
    

    This has a few downsides. Unlike the SFINAE solution (such as boost::enable_if), this doesn't give you exactly what you asked for. This compiles as long as an object of type Iter can be dereferenced yielding a value convertible to Unit*, which isn't quite the same thing. You have no guarantee that Iter is a completely STL-compliant iterator (it may just be another type which defines operator*), or that its value type is Unit* precisely.

    On the other hand, it's much simpler.

    0 讨论(0)
  • 2021-02-12 19:39

    You only want to iterate over containers of my_special_type? In that case:

    template <bool, typename T>
    struct enable_if;
    
    template <typename T>
    struct enable_if<true, T>
    {
        typedef T type;
    };
    
    template <typename T, typename U>
    struct is_same
    {
        enum {value = false};
    };
    
    template <typename T>
    struct is_same<T, T>
    {
        enum {value = true};
    };
    
    template <typename Iter>
    typename enable_if<is_same<typename Iter::value_type, your_special_type>::value,
                      void>::type
    function(Iter begin, Iter end)
    {
        // ...
    }
    
    0 讨论(0)
  • 2021-02-12 19:41

    You could use a SFINAE construct such as boost::enable_if which verifies if the nested typedef iterator::value_type is indeed of the appropriate type.

    template<class T, class Iterator>
    typename boost::enable_if<boost::is_same<typename Iterator::value_type, T> >::type
        f(Iterator i)
    {
        /* ... */
    }
    
    int main()
    {
        std::list<int> l;
        std::vector<int> v;
    
        f<int>(l.begin()); // OK
        f<int>(v.begin()); // OK
    
        std::vector<float> v2;
        f<int>(v2.begin()); /* Illegal */
    }
    

    This is what I understand from "a function that takes as input an iterator over any type of STL container, but only to those of a specific templated type", but my interpretation might be wrong.

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