2222#include " benchmark/benchmark.h"
2323#include " test_iterators.h"
2424#include " ../../GenerateInput.h"
25+ #include " ../../../std/containers/from_range_helpers.h"
2526
2627namespace support {
2728
@@ -172,8 +173,8 @@ void sequence_container_benchmarks(std::string container) {
172173 bool toggle = false ;
173174 for ([[maybe_unused]] auto _ : st) {
174175 std::vector<ValueType>& in = toggle ? in1 : in2;
175- auto first = in.data ();
176- auto last = in.data () + in. size ();
176+ auto first = in.begin ();
177+ auto last = in.end ();
177178 c.assign (cpp17_input_iterator (first), cpp17_input_iterator (last));
178179 toggle = !toggle;
179180 DoNotOptimizeData (c);
@@ -237,8 +238,8 @@ void sequence_container_benchmarks(std::string container) {
237238 std::vector<ValueType> in;
238239 std::generate_n (std::back_inserter (in), size, gen);
239240 DoNotOptimizeData (in);
240- auto first = in.data ();
241- auto last = in.data () + in. size ();
241+ auto first = in.begin ();
242+ auto last = in.end ();
242243
243244 const int small = 100 ; // arbitrary
244245 Container c;
@@ -264,8 +265,8 @@ void sequence_container_benchmarks(std::string container) {
264265 std::vector<ValueType> in;
265266 std::generate_n (std::back_inserter (in), size, gen);
266267 DoNotOptimizeData (in);
267- auto first = in.data ();
268- auto last = in.data () + in. size ();
268+ auto first = in.begin ();
269+ auto last = in.end ();
269270
270271 const int overflow = size / 10 ; // 10% of elements won't fit in the vector when we insert
271272 Container c;
@@ -290,8 +291,8 @@ void sequence_container_benchmarks(std::string container) {
290291 std::vector<ValueType> in;
291292 std::generate_n (std::back_inserter (in), size, gen);
292293 DoNotOptimizeData (in);
293- auto first = in.data ();
294- auto last = in.data () + in. size ();
294+ auto first = in.begin ();
295+ auto last = in.end ();
295296
296297 auto const overflow = 9 * (size / 10 ); // 90% of elements won't fit in the vector when we insert
297298 Container c;
@@ -448,6 +449,180 @@ void sequence_container_benchmarks(std::string container) {
448449 }
449450 });
450451 }
452+
453+ // //////////////////////////////////////////////////////////////////////////////////////////////
454+ // Additional benchmarks for vector<bool> iterator-pair and range-based operations
455+ // //////////////////////////////////////////////////////////////////////////////////////////////
456+
457+ static constexpr bool is_vector_bool = requires {
458+ typename Container::allocator_type;
459+ } && std::same_as<std::remove_cvref_t <Container>, std::vector<bool , typename Container::allocator_type>>;
460+
461+ if constexpr (is_vector_bool) {
462+ auto bench_vb = [&](std::string operation, auto f) {
463+ benchmark::RegisterBenchmark (container + " ::" + operation, f)->Arg (1024 )->Arg (1 << 16 )->Arg (1 << 20 );
464+ };
465+
466+ { // iterator-pair ctor
467+ auto bm = [&generators, &bench_vb, &tostr]<template <class > class Iter >(std::string iter) {
468+ for (auto gen : generators)
469+ bench_vb (" ctor(" + iter + " , " + iter + " )" + tostr (gen), [gen](auto & st) {
470+ auto const size = st.range (0 );
471+ std::vector<int > in;
472+ std::generate_n (std::back_inserter (in), size, gen);
473+ benchmark::DoNotOptimize (in);
474+ const auto begin = Iter (in.begin ());
475+ const auto end = Iter (in.end ());
476+ benchmark::DoNotOptimize (in);
477+
478+ for ([[maybe_unused]] auto _ : st) {
479+ Container c (begin, end); // we assume the destructor doesn't dominate the benchmark
480+ DoNotOptimizeData (c);
481+ }
482+ });
483+ };
484+ bm.template operator ()<forward_iterator>(" fwd_iter" );
485+ bm.template operator ()<random_access_iterator>(" ra_iter" );
486+ }
487+ { // iterator-pair assignment
488+ auto bm = [&generators, &bench_vb, &tostr]<template <class > class Iter >(std::string iter) {
489+ for (auto gen : generators)
490+ bench_vb (" assign(" + iter + " , " + iter + " )" + tostr (gen), [gen](auto & st) {
491+ auto const size = st.range (0 );
492+ std::vector<int > in1, in2;
493+ std::generate_n (std::back_inserter (in1), size, gen);
494+ std::generate_n (std::back_inserter (in2), size, gen);
495+ DoNotOptimizeData (in1);
496+ DoNotOptimizeData (in2);
497+
498+ Container c (in1.begin (), in1.end ());
499+ bool toggle = true ;
500+ for ([[maybe_unused]] auto _ : st) {
501+ auto & in = toggle ? in2 : in1;
502+ c.assign (Iter (in.begin ()), Iter (in.end ()));
503+ toggle = !toggle;
504+ DoNotOptimizeData (c);
505+ }
506+ });
507+ };
508+ bm.template operator ()<forward_iterator>(" fwd_iter" );
509+ bm.template operator ()<random_access_iterator>(" ra_iter" );
510+ }
511+ { // Iterator-pair insertion
512+ auto bm = [&generators, &bench_vb, &tostr]<template <class > class Iter >(std::string iter) {
513+ for (auto gen : generators)
514+ bench_vb (" insert(begin, " + iter + " , " + iter + " )" + tostr (gen), [gen](auto & st) {
515+ auto const size = st.range (0 );
516+ std::vector<int > in;
517+ Container c;
518+ std::generate_n (std::back_inserter (in), size, gen);
519+ std::generate_n (std::back_inserter (c), size, gen);
520+ DoNotOptimizeData (in);
521+ DoNotOptimizeData (c);
522+
523+ for ([[maybe_unused]] auto _ : st) {
524+ c.insert (c.begin (), Iter (in.begin ()), Iter (in.end ()));
525+ c.erase (c.begin () + size, c.end ()); // avoid growing indefinitely
526+ DoNotOptimizeData (c);
527+ }
528+ });
529+ };
530+ bm.template operator ()<forward_iterator>(" fwd_iter" );
531+ bm.template operator ()<random_access_iterator>(" ra_iter" );
532+ }
533+
534+ #if defined(__cpp_lib_containers_ranges) && __cpp_lib_containers_ranges >= 202202L
535+ { // Range-ctor
536+ auto bm = [&generators, &bench_vb, &tostr]<template <class , class > class Range >(std::string range) {
537+ for (auto gen : generators)
538+ bench_vb (" ctor(" + range + " )" + tostr (gen), [gen](auto & st) {
539+ auto const size = st.range (0 );
540+ std::vector<int > in;
541+ std::generate_n (std::back_inserter (in), size, gen);
542+ Range rg (std::ranges::begin (in), std::ranges::end (in));
543+ benchmark::DoNotOptimize (in);
544+
545+ for ([[maybe_unused]] auto _ : st) {
546+ Container c (std::from_range, rg); // we assume the destructor doesn't dominate the benchmark
547+ DoNotOptimizeData (c);
548+ }
549+ });
550+ };
551+ bm.template operator ()<forward_range_wrapper>(" fwd_range" );
552+ bm.template operator ()<random_access_range_wrapper>(" ra_range" );
553+ }
554+ { // Range-assignment
555+ auto bm = [&generators, &bench_vb, &tostr]<template <class , class > class Range >(std::string range) {
556+ for (auto gen : generators)
557+ bench_vb (" assign_range(" + range + " )" + tostr (gen), [gen](auto & st) {
558+ auto const size = st.range (0 );
559+ std::vector<int > in1, in2;
560+ std::generate_n (std::back_inserter (in1), size, gen);
561+ std::generate_n (std::back_inserter (in2), size, gen);
562+ Range rg1 (std::ranges::begin (in1), std::ranges::end (in1));
563+ Range rg2 (std::ranges::begin (in2), std::ranges::end (in2));
564+ DoNotOptimizeData (in1);
565+ DoNotOptimizeData (in2);
566+
567+ Container c (std::from_range, rg1);
568+ bool toggle = true ;
569+ for ([[maybe_unused]] auto _ : st) {
570+ auto & in = toggle ? rg2 : rg1;
571+ c.assign_range (in);
572+ toggle = !toggle;
573+ DoNotOptimizeData (c);
574+ }
575+ });
576+ };
577+ bm.template operator ()<forward_range_wrapper>(" fwd_range" );
578+ bm.template operator ()<random_access_range_wrapper>(" ra_range" );
579+ }
580+ { // Range-insertion
581+ auto bm = [&generators, &bench_vb, &tostr]<template <class , class > class Range >(std::string range) {
582+ for (auto gen : generators)
583+ bench_vb (" insert_range(" + range + " )" + tostr (gen), [gen](auto & st) {
584+ auto const size = st.range (0 );
585+ std::vector<int > in;
586+ Container c;
587+ std::generate_n (std::back_inserter (in), size, gen);
588+ std::generate_n (std::back_inserter (c), size, gen);
589+ Range rg (std::ranges::begin (in), std::ranges::end (in));
590+ DoNotOptimizeData (in);
591+ DoNotOptimizeData (c);
592+
593+ for ([[maybe_unused]] auto _ : st) {
594+ c.insert_range (c.begin (), in);
595+ c.erase (c.begin () + size, c.end ()); // avoid growing indefinitely
596+ DoNotOptimizeData (c);
597+ }
598+ });
599+ };
600+ bm.template operator ()<forward_range_wrapper>(" fwd_range" );
601+ bm.template operator ()<random_access_range_wrapper>(" ra_range" );
602+ }
603+ { // Range-append
604+ auto bm = [&generators, &bench_vb, &tostr]<template <class , class > class Range >(std::string range) {
605+ for (auto gen : generators)
606+ bench_vb (" append_range(" + range + " )" + tostr (gen), [gen](auto & st) {
607+ auto const size = st.range (0 );
608+ std::vector<int > in;
609+ std::generate_n (std::back_inserter (in), size, gen);
610+ Range rg (std::ranges::begin (in), std::ranges::end (in));
611+ DoNotOptimizeData (in);
612+
613+ Container c;
614+ for ([[maybe_unused]] auto _ : st) {
615+ c.append_range (in);
616+ c.erase (c.begin (), c.end ()); // avoid growing indefinitely
617+ DoNotOptimizeData (c);
618+ }
619+ });
620+ };
621+ bm.template operator ()<forward_range_wrapper>(" fwd_range" );
622+ bm.template operator ()<random_access_range_wrapper>(" ra_range" );
623+ }
624+ #endif
625+ }
451626}
452627
453628} // namespace support
0 commit comments