[PATCH] D25124: Support rvalue references in enumerate range adapter.

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 30 14:02:40 PDT 2016


dblaikie added inline comments.


> STLExtras.h:680
> +  // enable mutation of the underlying range if the type supports it.
> +  typename remove_rvalue_reference<R>::type Range;
>  };

So this is I think where it might be simpler than we're expecting.

If I change this line to:

  R  Range;

all the tests still pass. It may be worth adding a test with a container type (a simple wrapper container) that tracks its lifetime with flags to ensure this is doing the right thing rather than invoking subtle UB - and/or potentially exposing R as a member of enumerator_impl and using static_asserts of is_same to test that the container type for an enumeration over an rvalue is the value type, and the container type for an enumeration over an lvalue is a reference type.

Something like:

  struct Container {
    bool *Destroyed;
    Container(bool *Destroyed) : Destroyed(Destroyed) { } 
    /* begin and end, etc - could just have them both return nullptr */
    /* move ctor that just nulls out the Destroyed pointer */
    /* copy ops and move assign are implicitly disabled/removed by presence of a user declared move ctor */
    /* dtor that does: *Destroyed = true; */
  };
  
  bool Destroyed = false;
  {
    auto Enumerator = enumerate(C(&Destroyed));
    /* check Destroyed == false */
  }
  /* check Destroyed == true */

also you could check that for an lvalue, no copy/move is required:

  struct Container {
    Container();
    /* delete the move ctor and all the other move/copy ops will be implicitly deleted/not provided *(or delete them all if you want to be more explicit) */
    /* again, begin/end can just return nullptr */
  };
  Container c;
  enumerate(c); // this should compile, even though the container is not copyable/movable

The reason I think this works is "reference collapsing". When you pass an rvalue reference to X a template argument "T &&" then T is deduced X (the value type), but if you pass an lvalue, T is deduced to "X&". That's my understanding, at least.

https://reviews.llvm.org/D25124





More information about the llvm-commits mailing list