Home > other >  Why can't I manually define a template parameter?
Why can't I manually define a template parameter?

Time:05-22

I have a simple sample which provides:

  1. a struct template:

    #include <iostream>
    #include <vector>
    
    template <typename T>
    struct range_t
    {
        T b, e;
        range_t(T x, T y) : b(x), e(y) {}
        T begin() { return b; }
        T end() { return e; }
    };
    
  2. a function template:

    template <typename T>
    range_t<T> range(T b, T e)
    {
        return range_t<T>(b, e);
    }
    

I can use it to skip items in foreach loop of a (i.e) std::vector:

int main()
{
    std::vector<int> v{ 1, 2, 3, 4 };

    for (auto p : range(v.begin() 1, v.end()))
    {
        std::cout << p << " ";
    }
}

This works as intended, however I don't really understand the need of the function template (2).

I tried to write the foreach loop as this:

for (auto p : range_t<std::vector::const_iterator>(v.begin() 1, v.end()))

But for this I always got

error: template argument 1 is invalid

This might be a duplicate question, feel free to mark it as duplicate and please let me know the duplicated question which answers to all of these questions:

  1. Why is the template argument invalid here?

  2. (How) can I skip the function template?

  3. How can I create a function template which would work as this:

    myskipper would get only v as parameter in the foreach loop:

    template<typename T>
    range_t<T::const_iterator> myskipper(T c) {
      return range_t<T::const_iterator>(c.begin() 1, c.end());
    }
    
    ...
    for (auto p : myskipper(v)) ...
    

CodePudding user response:

Based on the comments and this article about iterator overflow, here a complete working example:

#include <iostream>
#include <vector>

template <typename T>
struct range_t
{
    T b, e;
    range_t(T x, T y) : b(x), e(y) {}
    T begin() { return b; }
    T end() { return e; }
};

template <typename T>
range_t<T> range(T b, T e)
{
    return range_t<T>(b, e);
}

template<typename T>
range_t<typename T::iterator> skip(T &c, typename T::size_type skipCount)
{
  return range_t<typename T::iterator>(c.begin()   std::min(c.size(), skipCount), c.end());
}

int main()
{
    std::vector<int> v{ 1, 2, 3, 4 };

    for (auto p : range(v.begin() 1, v.end()))
    {
        std::cout << p << " ";
    }
    
    std::cout << std::endl;
    
    for (auto p : range_t(v.begin() 1, v.end()))
    {
        std::cout << p << " ";
    }
    
    std::cout << std::endl;
    
    for (auto p : skip(v, 3))
    {
        std::cout << p << " ";
    }

    std::cout << std::endl;
}
  • Related