Muperman
Muperman

Reputation: 384

Pass Iterator to template but only accept certain data types

I am struggling a bit with passing iterators to functions.

I want to accomplish something like this. void func(MyClass* foo, numberOfFoo);

But I want to use iterators and it should support any stl-container.

I know I can write a function like this:

void foo(std::vector<MyClass>::const_iterator start, std::vector<MyClass>::const_iterator end){
    while (start != end){
        //Do stuff with *start, which has type MyClass
        ++start;
    }
}

I also know that I can write a Template like this:

template <class Iterator>
void foo( Iterator first, Iterator last){
    while (start != end){
        //Do stuff with *start, which has ANY type
        ++start;
    }
}

But I now want to write a Template, where the data type of the iterators are of type MyClass and no other.

In the end the following should happen:

std::vector<MyClass> vectorOfClass;
std::array<MyClass> arrayOfClass;
std::vector<int> vectorOfInt;

foo(vectorOfClass.begin(), vectorOfClass.end()); //Should compile
foo(arrayOfClass.begin(), arrayOfClass.end());   //Should compile
foo(vectorOfInt.begin(), vectorOfInt.end());     //Should not compile

Maybe the solution is very easy, but I don't know what to search for.

Thanks for your help already.

Upvotes: 1

Views: 133

Answers (1)

Ted Lyngmo
Ted Lyngmo

Reputation: 117258

If you don't need overloads, you don't need SFINAE, and could go for a simple static_assert using std::is_same_v and std::iterator_traits. A static_assert makes it possible to generate a really clear compilation error.

#include <iterator>     // std::iterator_traits
#include <type_traits>  // std::is_same_v

template<class It>
void foo(It first, It last) {
    static_assert(std::is_same_v<class std::iterator_traits<It>::value_type, MyClass>,
                  "Only ranges of MyClass objects are accepted by foo()");
    //...
}

Upvotes: 3

Related Questions