Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing iterators to class functions

Tags:

c++

stl

I'm trying to create a new templated class "CrazyBucket< T >" which has to hold multiple values of type T.

I want to create a constructor for this class that can accept any 2 forward iterators as its arguments and copy in those values (of type T) to the class instance.

Constructor:

CrazyBucket< T >::CrazyBucket( iterator< forward_iterator_tag, T > start,  iterator< forward_iterator_tag, T > end )
{ ... }

But when I try to call it with,

vector< int > vec;
vec.push_back( 4 );
CrazyBucket< int > bucket( vec.begin(), vec.end() );

I get the following error,

candidate constructor not viable: no known conversion from 'iterator' (aka '__wrap_iter<pointer>') to 'std::iterator<std::forward_iterator_tag, int>' for 1st argument

Any help with how I should define my constructor is much appreciated.

Thanks in advance.

like image 814
Akanes Avatar asked Oct 19 '22 18:10

Akanes


1 Answers

You can use SFINAE to exclude non-matching types in a fashion I think is close to what you want.

#include <iostream>
#include <iterator>
#include <vector>

template<class T>
class CrazyBucket
{
public:
    template<class It, typename = typename std::enable_if<
        std::is_same< typename std::iterator_traits<It>::value_type,T>::value>::type>
    CrazyBucket(It beg, It end)
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};

int main()
{
    std::vector<int> vInt;
    CrazyBucket<int> cbOK(vInt.begin(), vInt.end());

    int ar[10];
    CrazyBucket<int> cbAlsoOK(ar, ar+10);

    // uncomment for failure test case.
    //std::vector<double> vDbl;
    //CrazyBucket<int> cbFail(vDbl.begin(), vDbl.end());
}

Also accomplished with a static assertion:

template<class It>
CrazyBucket(It beg, It end)
{
    static_assert(std::is_same<T, typename std::iterator_traits<It>::value_type>::value,
       "failed to match iterator value type");
    std::cout << __PRETTY_FUNCTION__ << '\n';
}

Either is restrictive, and you should know that may not be the end goal you had in mind. For example, an iteration of short will naturally store as int without data loss, yet this kind of SFINAE will toss it. That too can be overcome with more expansion, but by that time I think you need to consider whether it is really worth it in the end.

Anyway, best of luck.

like image 78
WhozCraig Avatar answered Oct 23 '22 20:10

WhozCraig