[llvm] r225053 - Add an ArrayRef upcasting constructor from ArrayRef<U*> -> ArrayRef<T*> where T is a base of U.

David Blaikie dblaikie at gmail.com
Wed Dec 31 15:43:04 PST 2014


On Wed, Dec 31, 2014 at 3:33 PM, Michael Gottesman <mgottesman at apple.com>
wrote:

> Author: mgottesman
> Date: Wed Dec 31 17:33:18 2014
> New Revision: 225053
>
> URL: http://llvm.org/viewvc/llvm-project?rev=225053&view=rev
> Log:
> Add an ArrayRef upcasting constructor from ArrayRef<U*> -> ArrayRef<T*>
> where T is a base of U.
>
> Modified:
>     llvm/trunk/include/llvm/ADT/ArrayRef.h
>     llvm/trunk/unittests/ADT/ArrayRefTest.cpp
>
> Modified: llvm/trunk/include/llvm/ADT/ArrayRef.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ArrayRef.h?rev=225053&r1=225052&r2=225053&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/ArrayRef.h (original)
> +++ llvm/trunk/include/llvm/ADT/ArrayRef.h Wed Dec 31 17:33:18 2014
> @@ -112,6 +112,16 @@ namespace llvm {
>                   std::is_convertible<U *const *, T const
> *>::value>::type* = 0)
>        : Data(A.data()), Length(A.size()) {}
>
> +    /// Construct an ArrayRef<T*> from an ArrayRef<U*> where T is a super
> class
> +    /// of U. This uses SFINAE to ensure that only ArrayRefs with this
> property
> +    /// can be converted. This is an upcasting constructor.
> +    template <typename U>
> +    ArrayRef(const ArrayRef<U> &A,
> +             typename std::enable_if<std::is_base_of<
> +                 typename std::remove_pointer<T>::type,
> +                 typename std::remove_pointer<U>::type>::value>::type * =
> 0)
> +        : Data(reinterpret_cast<T const *>(A.data())), Length(A.size()) {}
> +
>      /// @}
>      /// @name Simple Operations
>      /// @{
>
> Modified: llvm/trunk/unittests/ADT/ArrayRefTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/ArrayRefTest.cpp?rev=225053&r1=225052&r2=225053&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/ADT/ArrayRefTest.cpp (original)
> +++ llvm/trunk/unittests/ADT/ArrayRefTest.cpp Wed Dec 31 17:33:18 2014
> @@ -90,4 +90,39 @@ TEST(ArrayRefTest, ConstConvert) {
>    a = ArrayRef<int *>(A);
>  }
>
> +struct A {
> +  int data;
> +
> +  A() : data(0) {}
> +};
> +
> +struct B : A {
> +  int data2;
> +
> +  B() : A(), data2(0) {}
> +};
> +
> +TEST(ArrayRefTest, UpcastConvert) {
> +  B Data[5];
> +
> +  for (unsigned i = 0, e = 5; i != e; ++i) {
> +    Data[i].data = i + 5;
> +    Data[i].data2 = i + 30;
> +  }
> +
> +  B *DataPtrs[5];
> +  for (unsigned i = 0, e = 5; i != e; ++i) {
> +    DataPtrs[i] = &Data[i];
> +  }
> +
> +  ArrayRef<B *> BArray(DataPtrs, 5);
> +  ArrayRef<A *> AArray(BArray);
> +
> +  EXPECT_TRUE(AArray.size() == 5);
> +  for (unsigned i = 0, e = 5; i != e; ++i) {
> +    A *a = AArray[i];
> +    EXPECT_TRUE(a->data == int(i + 5));
> +  }
> +}
> +
>

Maybe some static_assert+!is_convertible checks to demonstrate that the
SFINAE is behaving correctly and disallowing other conversions?


>  } // end anonymous namespace
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141231/eafe6ffe/attachment.html>


More information about the llvm-commits mailing list