Commit c18d575d authored by Tudor Bosman's avatar Tudor Bosman Committed by Dave Watson

Better support for folly::Range with non-const iterators underneath

Summary:
Implicitly construct Range<To> from Range<From> if From is implicitly
convertible to To.

Explicitly construct Range<To> from Range<From> if To is (explicitly)
constructible from From.

Add special-cases for Range<char*>, Range<unsigned char*> similar to the
ones for Range<const char*>, Range<const unsigned char*>.

Test Plan: test added

Reviewed By: philipp@fb.com

FB internal diff: D1182999
parent c2ed0fac
......@@ -240,20 +240,59 @@ public:
// direction.
template <class OtherIter, typename std::enable_if<
(std::is_same<Iter, const unsigned char*>::value &&
std::is_same<OtherIter, const char*>::value), int>::type = 0>
(std::is_same<OtherIter, const char*>::value ||
std::is_same<OtherIter, char*>::value)), int>::type = 0>
/* implicit */ Range(const Range<OtherIter>& other)
: b_(reinterpret_cast<const unsigned char*>(other.begin())),
e_(reinterpret_cast<const unsigned char*>(other.end())) {
}
template <class OtherIter, typename std::enable_if<
(std::is_same<Iter, unsigned char*>::value &&
std::is_same<OtherIter, char*>::value), int>::type = 0>
/* implicit */ Range(const Range<OtherIter>& other)
: b_(reinterpret_cast<unsigned char*>(other.begin())),
e_(reinterpret_cast<unsigned char*>(other.end())) {
}
template <class OtherIter, typename std::enable_if<
(std::is_same<Iter, const char*>::value &&
std::is_same<OtherIter, const unsigned char*>::value), int>::type = 0>
(std::is_same<OtherIter, const unsigned char*>::value ||
std::is_same<OtherIter, unsigned char*>::value)), int>::type = 0>
explicit Range(const Range<OtherIter>& other)
: b_(reinterpret_cast<const char*>(other.begin())),
e_(reinterpret_cast<const char*>(other.end())) {
}
template <class OtherIter, typename std::enable_if<
(std::is_same<Iter, char*>::value &&
std::is_same<OtherIter, unsigned char*>::value), int>::type = 0>
explicit Range(const Range<OtherIter>& other)
: b_(reinterpret_cast<char*>(other.begin())),
e_(reinterpret_cast<char*>(other.end())) {
}
// Allow implicit conversion from Range<From> to Range<To> if From is
// implicitly convertible to To.
template <class OtherIter, typename std::enable_if<
(!std::is_same<Iter, OtherIter>::value &&
std::is_convertible<OtherIter, Iter>::value), int>::type = 0>
/* implicit */ Range(const Range<OtherIter>& other)
: b_(other.begin()),
e_(other.end()) {
}
// Allow explicit conversion from Range<From> to Range<To> if From is
// explicitly convertible to To.
template <class OtherIter, typename std::enable_if<
(!std::is_same<Iter, OtherIter>::value &&
!std::is_convertible<OtherIter, Iter>::value &&
std::is_constructible<Iter, const OtherIter&>::value), int>::type = 0>
explicit Range(const Range<OtherIter>& other)
: b_(other.begin()),
e_(other.end()) {
}
void clear() {
b_ = Iter();
e_ = Iter();
......@@ -616,7 +655,9 @@ Range<Iter> makeRange(Iter first, Iter last) {
}
typedef Range<const char*> StringPiece;
typedef Range<char*> MutableStringPiece;
typedef Range<const unsigned char*> ByteRange;
typedef Range<unsigned char*> MutableByteRange;
std::ostream& operator<<(std::ostream& os, const StringPiece& piece);
......
......@@ -908,3 +908,17 @@ TYPED_TEST(NeedleFinderTest, NoSegFault) {
}
}
TEST(NonConstTest, StringPiece) {
std::string hello("hello");
MutableStringPiece sp(&hello.front(), hello.size());
sp[0] = 'x';
EXPECT_EQ("xello", hello);
{
StringPiece s(sp);
EXPECT_EQ("xello", s);
}
{
ByteRange r1(sp);
MutableByteRange r2(sp);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment