Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

specializing functions on stl style container types

If i have a type T, what is a useful way to inspect it at compile time to see whether its an STL-style container (for an arbitrary value type) or not?
(Assumption: pointers, reference, etc. already stripped)

Starting code:

template<class T> // (1)
void f(T&) {} 

template<class T> // (2)
void f(std::vector<T>&) {} 

void test() 
{
    int a;
    std::vector<int> b;
    f(a);
    f(b);
}

Now this works fine, but what if i want to generalize the container (i.e. not define (3), (4), ... explicitly)?

Utilizing SFINAE and typelists would reduce the code somewhat, but is there a better way?
Or is there an idiom for specializing based on concepts?
Or could i somehow utilize SFINAE to selectively enable only the desired specializations?

As a sidenote, i can't use iterators - i am trying to specialize based on functions that receive Ts as parameters.


As per MSalters answer:

template<class T>
void f(T&, ...) {
    std::cout << "flat" << std::endl; 
}

template<class Cont>
void f(Cont& c, typename Cont::iterator begin = Cont().begin(),
                typename Cont::iterator end   = Cont().end()) {
    std::cout << "container" << std::endl; 
}

(The variable argument list is needed to make the first f the least preferred version to solve ambiguity errors)


1 Answers

STLcontainers by definition have a typedef iterator, with 2 methods begin() and end() retruning them. This range is what the container contains. If there's no such range, it's not a container in the STL sense. So I'd sugegst something along the line of (not checked)

template<typename CONTAINER>
void f(CONTAINER& c,
       typename CONTAINER::iterator begin = c.begin(),
       typename CONTAINER::iterator end = c.end())
{ }
like image 58
MSalters Avatar answered Dec 13 '25 01:12

MSalters



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!