@@ -375,6 +375,16 @@ namespace csv {
375375 write_range_impl (container);
376376 return *this ;
377377 }
378+
379+ /* * Write a row-like object that exposes to_sv_range(). */
380+ template <typename RowLike>
381+ DelimWriter& operator <<(const RowLike& row)
382+ requires internals::has_to_sv_range<RowLike>
383+ && !internals::csv_string_field_range<RowLike> {
384+ append_row_like (row);
385+ finish_write_call ();
386+ return *this ;
387+ }
378388 #else
379389 /* * Write a range of string-like fields as one delimited row.
380390 *
@@ -432,12 +442,13 @@ namespace csv {
432442 }
433443
434444 private:
435- /* * Helper to write a range of values, handling first element undelimited,
436- * rest prefixed with delimiter. Inlines aggressively across both C++20 and
437- * C++11 operator<< entry points.
445+ /* * Append delimited fields from a range without terminating the record.
446+ *
447+ * Shared by single-row writes and bulk row appends so escaping and
448+ * delimiter handling stay on one code path.
438449 */
439450 template <typename Range>
440- inline void write_range_impl ( const Range& record) {
451+ inline void append_range_fields ( Range& & record) {
441452 auto it = std::begin (record);
442453 auto end = std::end (record);
443454
@@ -450,6 +461,14 @@ namespace csv {
450461 batch_buffer_.push_back (Delim);
451462 write_field (*it);
452463 }
464+ }
465+
466+ /* * Helper to write a complete range-backed row and apply the normal
467+ * end-of-record and flush policy for operator<< entry points.
468+ */
469+ template <typename Range>
470+ inline void write_range_impl (const Range& record) {
471+ append_range_fields (record);
453472
454473 end_record ();
455474 finish_write_call ();
@@ -467,23 +486,6 @@ namespace csv {
467486
468487 end_record ();
469488 }
470-
471- template <std::ranges::input_range Range>
472- requires std::convertible_to<std::ranges::range_reference_t <Range>, csv::string_view>
473- void append_range_fields (Range&& record) {
474- auto it = std::begin (record);
475- auto end = std::end (record);
476-
477- if (it != end) {
478- write_field (*it);
479- ++it;
480- }
481-
482- for (; it != end; ++it) {
483- batch_buffer_.push_back (Delim);
484- write_field (*it);
485- }
486- }
487489 #endif
488490
489491 template <
0 commit comments