Skip to content
This repository was archived by the owner on Dec 8, 2021. It is now read-only.

Commit 4b9aa17

Browse files
authored
fix!: avoid single-arg forwarding c'tor (#1233)
Single-argument forwarding constructors can hide implicitly generated copy/move constructors. Even if this issue is avoided with the proper use of SFINAE, clang-tidy may still complain (incorrectly, I think). http://clang.llvm.org/extra/clang-tidy/checks/bugprone-forwarding-reference-overload.html To fix this I renamed the class `StreamOf` -> `TupleStream`. I then changed its constructor to accept to iterators instead of a single range. Then I added a `StreamOf<T>()` non-member factory function. This should make it so our existing uses all continue to work. So, this really shouldn't be much of an API break.
1 parent 21c93a8 commit 4b9aa17

2 files changed

Lines changed: 35 additions & 28 deletions

File tree

google/cloud/spanner/row.h

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -372,10 +372,12 @@ class TupleStreamIterator {
372372
};
373373

374374
/**
375-
* A `StreamOf<Tuple>` defines a range that parses `Tuple` objects from the
375+
* A `TupleStream<Tuple>` defines a range that parses `Tuple` objects from the
376376
* given range of `RowStreamIterator`s.
377377
*
378-
* Users will typically use this class in a range-for loop as follows:
378+
* Users create instances using the `StreamOf<T>(range)` non-member factory
379+
* function (defined below). The following is a typical usage of this class in
380+
* a range-for loop.
379381
*
380382
* @code
381383
* auto row_range = ...
@@ -397,40 +399,45 @@ class TupleStreamIterator {
397399
* @tparam Tuple the std::tuple<...> to parse each `Row` into.
398400
*/
399401
template <typename Tuple>
400-
class StreamOf {
402+
class TupleStream {
401403
public:
402404
using iterator = TupleStreamIterator<Tuple>;
403405
static_assert(internal::IsTuple<Tuple>::value,
404-
"StreamOf<T> requires a std::tuple parameter");
405-
406-
/**
407-
* Creates a `StreamOf<Tuple>` by wrapping the given @p range. The `RowRange`
408-
* must be a range defined by `RowStreamIterator` objects.
409-
*
410-
* @note ownership of the @p range is not transferred, so it must outlive the
411-
* `StreamOf`.
412-
*
413-
* @tparam RowRange must be a range defined by `RowStreamIterator`s.
414-
*/
415-
template <typename RowRange>
416-
explicit StreamOf(RowRange&& range)
417-
: begin_(std::begin(std::forward<RowRange>(range)),
418-
std::end(std::forward<RowRange>(range))) {
419-
using T = decltype(std::begin(range));
420-
static_assert(std::is_same<RowStreamIterator, T>::value,
421-
"StreamOf must be given a RowStreamIterator range.");
422-
static_assert(std::is_lvalue_reference<decltype(range)>::value,
423-
"range must be an lvalue since it must outlive StreamOf");
424-
}
406+
"TupleStream<T> requires a std::tuple parameter");
425407

426408
iterator begin() const { return begin_; }
427409
iterator end() const { return end_; }
428410

429411
private:
412+
template <typename T, typename RowRange>
413+
friend TupleStream<T> StreamOf(RowRange&& range);
414+
415+
template <typename It>
416+
explicit TupleStream(It&& start, It&& end)
417+
: begin_(std::forward<It>(start), std::forward<It>(end)) {}
418+
430419
iterator begin_;
431420
iterator end_;
432421
};
433422

423+
/**
424+
* A factory that creates a `TupleStream<Tuple>` by wrapping the given @p
425+
* range. The `RowRange` must be a range defined by `RowStreamIterator`
426+
* objects.
427+
*
428+
* @note ownership of the @p range is not transferred, so it must outlive the
429+
* returned `TupleStream`.
430+
*
431+
* @tparam RowRange must be a range defined by `RowStreamIterator`s.
432+
*/
433+
template <typename Tuple, typename RowRange>
434+
TupleStream<Tuple> StreamOf(RowRange&& range) {
435+
static_assert(std::is_lvalue_reference<decltype(range)>::value,
436+
"range must be an lvalue since it must outlive StreamOf");
437+
return TupleStream<Tuple>(std::begin(std::forward<RowRange>(range)),
438+
std::end(std::forward<RowRange>(range)));
439+
}
440+
434441
/**
435442
* Returns the only row from a range that contains exactly one row.
436443
*

google/cloud/spanner/row_test.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ TEST(TupleStreamIterator, Error) {
403403
EXPECT_EQ(it, end);
404404
}
405405

406-
TEST(StreamOf, Basics) {
406+
TEST(TupleStream, Basics) {
407407
std::vector<Row> rows;
408408
rows.emplace_back(MakeTestRow(1, "foo", true));
409409
rows.emplace_back(MakeTestRow(2, "bar", true));
@@ -438,7 +438,7 @@ TEST(StreamOf, Basics) {
438438
EXPECT_EQ(it, end);
439439
}
440440

441-
TEST(StreamOf, RangeForLoop) {
441+
TEST(TupleStream, RangeForLoop) {
442442
std::vector<Row> rows;
443443
rows.emplace_back(MakeTestRow({{"num", Value(2)}}));
444444
rows.emplace_back(MakeTestRow({{"num", Value(3)}}));
@@ -454,7 +454,7 @@ TEST(StreamOf, RangeForLoop) {
454454
EXPECT_EQ(product, 30);
455455
}
456456

457-
TEST(StreamOf, IterationError) {
457+
TEST(TupleStream, IterationError) {
458458
std::vector<StatusOr<Row>> rows;
459459
rows.emplace_back(MakeTestRow(1, "foo", true));
460460
rows.emplace_back(Status(StatusCode::kUnknown, "some error"));
@@ -463,7 +463,7 @@ TEST(StreamOf, IterationError) {
463463
RowRange range(MakeRowStreamIteratorSource(rows));
464464

465465
using RowType = std::tuple<std::int64_t, std::string, bool>;
466-
StreamOf<RowType> stream(range);
466+
auto stream = StreamOf<RowType>(range);
467467

468468
auto end = stream.end();
469469
auto it = stream.begin();

0 commit comments

Comments
 (0)