Boost logo

Boost :

Subject: Re: [boost] [range] [general] making member functions SFINAE-friendly
From: Pyry Jahkola (pyry.jahkola_at_[hidden])
Date: 2013-02-19 13:18:08


On 2013-02-19 17:01:14 +0000, Jonathan Wakely said:

> On 19 February 2013 17:00, Thorsten Ottosen wrote:
>>
>> Would using enable_if on size() not solve the problem?
>
> It's not a template function, so you can't.

I'm not suggesting to actually use the following hack in
boost::iterator_range, but since you claimed the opposite, this trick
has the wished SFINAE behavior in C++11.

/Pyry.

* * *

#include <list>
#include <vector>

struct zero {
    template <typename T>
    T && operator+(T && x) const { return std::forward<T>(x); }
};
template <typename T> struct always_zero { using type = zero; };

template <typename I> struct iterator_range {
    I b, e;
    iterator_range(I b, I e) : b(b), e(e) {}

    // SFINAE trick:

    template <typename Ignore=void>
    auto size(typename always_zero<Ignore>::type z={}) -> decltype(z + e - b) {
        return e - b;
    }
};

using std::begin;
using std::end;

template <typename R>
auto make_iterator_range(R const & r) -> iterator_range<decltype(begin(r))> {
    return iterator_range<decltype(begin(r))>(begin(r), end(r));
}

int main() {
    std::list<int> list;
    std::vector<int> vector;
    auto r1 = make_iterator_range(list); // no error
    auto r2 = make_iterator_range(vector);
    // r1.size(); // compiler error
    r2.size();
}

* * *

-- 
Pyry Jahkola
pyry.jahkola_at_[hidden]
https://twitter.com/pyrtsa

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk