ericniebler / range-v3

Range library for C++14/17/20, basis for C++20's std::ranges
Other
4.13k stars 439 forks source link

disable_sized_range not enough to save ranges::equal() #322

Closed tonyelewis closed 8 years ago

tonyelewis commented 8 years ago

The following code fails to compile with libstdc++'s debug mode (under both GCC and Clang):

#define _GLIBCXX_DEBUG
#define RANGES_NO_STD_FORWARD_DECLARATIONS
#include <range/v3/all.hpp>

#include <list>

class int_list_wrapper final {
private:
    std::list<int> the_list;

public:
    using const_iterator = std::list<int>::const_iterator;

    int_list_wrapper() = default;
    int_list_wrapper(const std::list<int> &arg_list) : the_list ( arg_list ) {}

    const_iterator begin() const { return the_list.begin(); }
    const_iterator end  () const { return the_list.end  (); }
};

namespace ranges {
    template <> struct disable_sized_range<int_list_wrapper> : std::true_type {};
}

int main() {
    const int_list_wrapper s1 = { std::list<int>{ 0, 1, 2 } };
    const int_list_wrapper s2 = { std::list<int>{ 0, 1, 2 } };

    const bool are_equal = ranges::equal( s1, s2 );
}

I think the disable_sized_range has disabled SizedRange for int_list_wrapper - indeed the following all pass :

static_assert( ! ranges::SizedRange<      int_list_wrapper  >(), "" );
static_assert( ! ranges::SizedRange<      int_list_wrapper &>(), "" );
static_assert( ! ranges::SizedRange<const int_list_wrapper  >(), "" );
static_assert( ! ranges::SizedRange<const int_list_wrapper &>(), "" );

...but the ranges::equal() still fails because the compiler has to compile the code here even if it won't run it at runtime.

Thanks very much.

tonyelewis commented 8 years ago

This relates to the libstdc++ debug safe iterator issues in #231 and #294.

CaseyCarter commented 8 years ago

You don't need to disable_sized_range<int_list_wrapper>. int_list_wrapper does not have a bogus member/non-member size that makes it look like a SizedRange. What you do need to do is disable SizedIteratorRange for its iterators, since they have an unconstrained operator- that is ill-formed.

tonyelewis commented 8 years ago

I'm an idiot. Sorry. I was originally trying disable_sized_iterator_range (which I use quite a lot) and it didn't work but I now realise that was for another reason and I've been on a wild goose chase. Apologies for wasting your time and thanks for the quick, helpful response.

gnzlbg commented 8 years ago

Why do you use it quite a lot?

On Saturday, 16 April 2016, Tony E Lewis notifications@github.com wrote:

Closed #322 https://github.com/ericniebler/range-v3/issues/322.

— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub https://github.com/ericniebler/range-v3/issues/322#event-630086783

Dipl.-Ing. Gonzalo Brito Gadeschi Institute of Aerodynamics and Chair of Fluid Mechanics RWTH Aachen University Wuellnerstraße 5a D-52062 Aachen Germany Phone: ++49-(0)241-80-94821 Fax: ++49-(0)241-80-92257 E-mail: g.brito@aia.rwth-aachen.de Internet: www.aia.rwth-aachen.de

tonyelewis commented 8 years ago

Sorry: when is said "quite a lot", I meant something like: often enough that I have little excuse for messing it up here.

I use disable sized_iterator_range in 12 of my .cpp files, each added to fix a compilation error in my GCC debug build.

Does that answer the question?