Skip to content

Commit 1bc59dc

Browse files
authored
Finish cxx version bump (#1948)
* `CMakeLists.txt`: drop hopefully obsolete code * README.md: update * Unbreak `BENCHMARK_HAS_CXX11` macro 835365f stopped defining it, but didn't un-conditionalize the code guarded under it... * Drop `BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK` We no longer support such an old gcc version * `docs/user_guide.md`: proofread * Add a test to ensure that `benchmark.h` remains C++14 header * Revert `[[maybe_unused]]` changes - it requires C++17 * Also support C++11 standard for using the library I don't think we want to support C++03 though, but i suppose C++11 is palatable, at least right now.
1 parent 45ded53 commit 1bc59dc

File tree

11 files changed

+113
-80
lines changed

11 files changed

+113
-80
lines changed

CMakeLists.txt

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -306,17 +306,11 @@ if (BENCHMARK_USE_LIBCXX)
306306
endif()
307307
endif(BENCHMARK_USE_LIBCXX)
308308

309-
set(EXTRA_CXX_FLAGS "")
310-
if (WIN32 AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
311-
# Clang on Windows fails to compile the regex feature check under C++11
312-
set(EXTRA_CXX_FLAGS "-DCMAKE_CXX_STANDARD=14")
313-
endif()
314-
315309
# C++ feature checks
316310
# Determine the correct regular expression engine to use
317-
cxx_feature_check(STD_REGEX ${EXTRA_CXX_FLAGS})
318-
cxx_feature_check(GNU_POSIX_REGEX ${EXTRA_CXX_FLAGS})
319-
cxx_feature_check(POSIX_REGEX ${EXTRA_CXX_FLAGS})
311+
cxx_feature_check(STD_REGEX)
312+
cxx_feature_check(GNU_POSIX_REGEX)
313+
cxx_feature_check(POSIX_REGEX)
320314
if(NOT HAVE_STD_REGEX AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX)
321315
message(FATAL_ERROR "Failed to determine the source files for the regular expression backend")
322316
endif()

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ IRC channels:
5050
5151
## Requirements
5252
53-
The library can be used with C++03. However, it requires C++14 to build,
53+
The library can be used with C++11. However, it requires C++17 to build,
5454
including compiler and standard library support.
5555
5656
_See [dependencies.md](docs/dependencies.md) for more details regarding supported
@@ -190,7 +190,7 @@ be under the build directory you created.
190190
```bash
191191
# Example on linux after running the build steps above. Assumes the
192192
# `benchmark` and `build` directories are under the current directory.
193-
$ g++ mybenchmark.cc -std=c++14 -isystem benchmark/include \
193+
$ g++ mybenchmark.cc -std=c++11 -isystem benchmark/include \
194194
-Lbenchmark/build/src -lbenchmark -lpthread -o mybenchmark
195195
```
196196

docs/user_guide.md

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ BENCHMARK(BM_SetInsert)->Apply(CustomArguments);
462462
463463
### Passing Arbitrary Arguments to a Benchmark
464464
465-
In C++11 it is possible to define a benchmark that takes an arbitrary number
465+
It is possible to define a benchmark that takes an arbitrary number
466466
of extra arguments. The `BENCHMARK_CAPTURE(func, test_case_name, ...args)`
467467
macro creates a benchmark that invokes `func` with the `benchmark::State` as
468468
the first argument followed by the specified `args...`.
@@ -563,22 +563,19 @@ template <class Q> void BM_Sequential(benchmark::State& state) {
563563
state.SetBytesProcessed(
564564
static_cast<int64_t>(state.iterations())*state.range(0));
565565
}
566-
// C++03
567-
BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue<int>)->Range(1<<0, 1<<10);
568566

569-
// C++11 or newer, you can use the BENCHMARK macro with template parameters:
567+
// You can use the BENCHMARK macro with template parameters:
570568
BENCHMARK(BM_Sequential<WaitQueue<int>>)->Range(1<<0, 1<<10);
571569

570+
// Old, legacy verbose C++03 syntax:
571+
BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue<int>)->Range(1<<0, 1<<10);
572+
572573
```
573574
574575
Three macros are provided for adding benchmark templates.
575576
576577
```c++
577-
#ifdef BENCHMARK_HAS_CXX11
578578
#define BENCHMARK(func<...>) // Takes any number of parameters.
579-
#else // C++ < C++11
580-
#define BENCHMARK_TEMPLATE(func, arg1)
581-
#endif
582579
#define BENCHMARK_TEMPLATE1(func, arg1)
583580
#define BENCHMARK_TEMPLATE2(func, arg1, arg2)
584581
```
@@ -740,12 +737,10 @@ is 1k a 1000 (default, `benchmark::Counter::OneK::kIs1000`), or 1024
740737
state.counters["BytesProcessed"] = Counter(state.range(0), benchmark::Counter::kIsIterationInvariantRate, benchmark::Counter::OneK::kIs1024);
741738
```
742739

743-
When you're compiling in C++11 mode or later you can use `insert()` with
744-
`std::initializer_list`:
740+
You can use `insert()` with `std::initializer_list`:
745741

746742
<!-- {% raw %} -->
747743
```c++
748-
// With C++11, this can be done:
749744
state.counters.insert({{"Foo", numFoos}, {"Bar", numBars}, {"Baz", numBazs}});
750745
// ... instead of:
751746
state.counters["Foo"] = numFoos;
@@ -1249,7 +1244,7 @@ static void BM_test_ranged_fo(benchmark::State & state) {
12491244
12501245
## A Faster KeepRunning Loop
12511246
1252-
In C++11 mode, a ranged-based for loop should be used in preference to
1247+
A ranged-based for loop should be used in preference to
12531248
the `KeepRunning` loop for running the benchmarks. For example:
12541249
12551250
```c++

include/benchmark/benchmark.h

Lines changed: 61 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,14 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
191191
TypeName(const TypeName&) = delete; \
192192
TypeName& operator=(const TypeName&) = delete
193193

194+
#ifdef BENCHMARK_HAS_CXX17
195+
#define BENCHMARK_UNUSED [[maybe_unused]]
196+
#elif defined(__GNUC__) || defined(__clang__)
197+
#define BENCHMARK_UNUSED __attribute__((unused))
198+
#else
199+
#define BENCHMARK_UNUSED
200+
#endif
201+
194202
// Used to annotate functions, methods and classes so they
195203
// are not optimized by the compiler. Useful for tests
196204
// where you expect loops to stay in place churning cycles
@@ -303,6 +311,18 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
303311
#endif // _MSC_VER_
304312

305313
namespace benchmark {
314+
315+
namespace internal {
316+
#if (__cplusplus < 201402L || (defined(_MSC_VER) && _MSVC_LANG < 201402L))
317+
template <typename T, typename... Args>
318+
std::unique_ptr<T> make_unique(Args&&... args) {
319+
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
320+
}
321+
#else
322+
using ::std::make_unique;
323+
#endif
324+
} // namespace internal
325+
306326
class BenchmarkReporter;
307327
class State;
308328

@@ -472,7 +492,7 @@ BENCHMARK_EXPORT Benchmark* RegisterBenchmarkInternal(
472492

473493
// Ensure that the standard streams are properly initialized in every TU.
474494
BENCHMARK_EXPORT int InitializeStreams();
475-
[[maybe_unused]] static int stream_init_anchor = InitializeStreams();
495+
BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
476496

477497
} // namespace internal
478498

@@ -1026,7 +1046,7 @@ inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningInternal(IterationCount n,
10261046
}
10271047

10281048
struct State::StateIterator {
1029-
struct [[maybe_unused]] Value {};
1049+
struct BENCHMARK_UNUSED Value {};
10301050
typedef std::forward_iterator_tag iterator_category;
10311051
typedef Value value_type;
10321052
typedef Value reference;
@@ -1371,27 +1391,24 @@ class LambdaBenchmark : public Benchmark {
13711391
inline internal::Benchmark* RegisterBenchmark(const std::string& name,
13721392
internal::Function* fn) {
13731393
return internal::RegisterBenchmarkInternal(
1374-
std::make_unique<internal::FunctionBenchmark>(name, fn));
1394+
benchmark::internal::make_unique<internal::FunctionBenchmark>(name, fn));
13751395
}
13761396

13771397
template <class Lambda>
13781398
internal::Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn) {
13791399
using BenchType =
13801400
internal::LambdaBenchmark<typename std::decay<Lambda>::type>;
13811401
return internal::RegisterBenchmarkInternal(
1382-
std::make_unique<BenchType>(name, std::forward<Lambda>(fn)));
1402+
benchmark::internal::make_unique<BenchType>(name,
1403+
std::forward<Lambda>(fn)));
13831404
}
13841405

1385-
#if (!defined(BENCHMARK_GCC_VERSION) || BENCHMARK_GCC_VERSION >= 409)
13861406
template <class Lambda, class... Args>
13871407
internal::Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn,
13881408
Args&&... args) {
13891409
return benchmark::RegisterBenchmark(
13901410
name, [=](benchmark::State& st) { fn(st, args...); });
13911411
}
1392-
#else
1393-
#define BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
1394-
#endif
13951412

13961413
// The base class for all fixture tests.
13971414
class Fixture : public internal::Benchmark {
@@ -1442,13 +1459,14 @@ class Fixture : public internal::Benchmark {
14421459
#define BENCHMARK_PRIVATE_DECLARE(n) \
14431460
/* NOLINTNEXTLINE(misc-use-anonymous-namespace) */ \
14441461
static ::benchmark::internal::Benchmark const* const BENCHMARK_PRIVATE_NAME( \
1445-
n) [[maybe_unused]]
1462+
n) BENCHMARK_UNUSED
14461463

14471464
#define BENCHMARK(...) \
14481465
BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \
14491466
(::benchmark::internal::RegisterBenchmarkInternal( \
1450-
std::make_unique<::benchmark::internal::FunctionBenchmark>( \
1451-
#__VA_ARGS__, __VA_ARGS__)))
1467+
benchmark::internal::make_unique< \
1468+
::benchmark::internal::FunctionBenchmark>(#__VA_ARGS__, \
1469+
__VA_ARGS__)))
14521470

14531471
// Old-style macros
14541472
#define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
@@ -1469,11 +1487,12 @@ class Fixture : public internal::Benchmark {
14691487
//}
14701488
// /* Registers a benchmark named "BM_takes_args/int_string_test` */
14711489
// BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc"));
1472-
#define BENCHMARK_CAPTURE(func, test_case_name, ...) \
1473-
BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \
1474-
(::benchmark::internal::RegisterBenchmarkInternal( \
1475-
std::make_unique<::benchmark::internal::FunctionBenchmark>( \
1476-
#func "/" #test_case_name, \
1490+
#define BENCHMARK_CAPTURE(func, test_case_name, ...) \
1491+
BENCHMARK_PRIVATE_DECLARE(_benchmark_) = \
1492+
(::benchmark::internal::RegisterBenchmarkInternal( \
1493+
benchmark::internal::make_unique< \
1494+
::benchmark::internal::FunctionBenchmark>( \
1495+
#func "/" #test_case_name, \
14771496
[](::benchmark::State& st) { func(st, __VA_ARGS__); })))
14781497

14791498
// This will register a benchmark for a templatized function. For example:
@@ -1484,22 +1503,24 @@ class Fixture : public internal::Benchmark {
14841503
// BENCHMARK_TEMPLATE(BM_Foo, 1);
14851504
//
14861505
// will register BM_Foo<1> as a benchmark.
1487-
#define BENCHMARK_TEMPLATE1(n, a) \
1488-
BENCHMARK_PRIVATE_DECLARE(n) = \
1489-
(::benchmark::internal::RegisterBenchmarkInternal( \
1490-
std::make_unique<::benchmark::internal::FunctionBenchmark>( \
1491-
#n "<" #a ">", n<a>)))
1492-
1493-
#define BENCHMARK_TEMPLATE2(n, a, b) \
1494-
BENCHMARK_PRIVATE_DECLARE(n) = \
1495-
(::benchmark::internal::RegisterBenchmarkInternal( \
1496-
std::make_unique<::benchmark::internal::FunctionBenchmark>( \
1497-
#n "<" #a "," #b ">", n<a, b>)))
1498-
1499-
#define BENCHMARK_TEMPLATE(n, ...) \
1500-
BENCHMARK_PRIVATE_DECLARE(n) = \
1501-
(::benchmark::internal::RegisterBenchmarkInternal( \
1502-
std::make_unique<::benchmark::internal::FunctionBenchmark>( \
1506+
#define BENCHMARK_TEMPLATE1(n, a) \
1507+
BENCHMARK_PRIVATE_DECLARE(n) = \
1508+
(::benchmark::internal::RegisterBenchmarkInternal( \
1509+
benchmark::internal::make_unique< \
1510+
::benchmark::internal::FunctionBenchmark>(#n "<" #a ">", n<a>)))
1511+
1512+
#define BENCHMARK_TEMPLATE2(n, a, b) \
1513+
BENCHMARK_PRIVATE_DECLARE(n) = \
1514+
(::benchmark::internal::RegisterBenchmarkInternal( \
1515+
benchmark::internal::make_unique< \
1516+
::benchmark::internal::FunctionBenchmark>(#n "<" #a "," #b ">", \
1517+
n<a, b>)))
1518+
1519+
#define BENCHMARK_TEMPLATE(n, ...) \
1520+
BENCHMARK_PRIVATE_DECLARE(n) = \
1521+
(::benchmark::internal::RegisterBenchmarkInternal( \
1522+
benchmark::internal::make_unique< \
1523+
::benchmark::internal::FunctionBenchmark>( \
15031524
#n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>)))
15041525

15051526
// This will register a benchmark for a templatized function,
@@ -1517,12 +1538,13 @@ class Fixture : public internal::Benchmark {
15171538
#define BENCHMARK_TEMPLATE1_CAPTURE(func, a, test_case_name, ...) \
15181539
BENCHMARK_CAPTURE(func<a>, test_case_name, __VA_ARGS__)
15191540

1520-
#define BENCHMARK_TEMPLATE2_CAPTURE(func, a, b, test_case_name, ...) \
1521-
BENCHMARK_PRIVATE_DECLARE(func) = \
1522-
(::benchmark::internal::RegisterBenchmarkInternal( \
1523-
std::make_unique<::benchmark::internal::FunctionBenchmark>( \
1524-
#func "<" #a "," #b ">" \
1525-
"/" #test_case_name, \
1541+
#define BENCHMARK_TEMPLATE2_CAPTURE(func, a, b, test_case_name, ...) \
1542+
BENCHMARK_PRIVATE_DECLARE(func) = \
1543+
(::benchmark::internal::RegisterBenchmarkInternal( \
1544+
benchmark::internal::make_unique< \
1545+
::benchmark::internal::FunctionBenchmark>( \
1546+
#func "<" #a "," #b ">" \
1547+
"/" #test_case_name, \
15261548
[](::benchmark::State& st) { func<a, b>(st, __VA_ARGS__); })))
15271549

15281550
#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
@@ -1591,7 +1613,7 @@ class Fixture : public internal::Benchmark {
15911613
#define BENCHMARK_PRIVATE_REGISTER_F(TestName) \
15921614
BENCHMARK_PRIVATE_DECLARE(TestName) = \
15931615
(::benchmark::internal::RegisterBenchmarkInternal( \
1594-
std::make_unique<TestName>()))
1616+
benchmark::internal::make_unique<TestName>()))
15951617

15961618
// This macro will define and register a benchmark within a fixture class.
15971619
#define BENCHMARK_F(BaseClass, Method) \

test/BUILD

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,27 @@ cc_library(
102102
["*_test.cc"],
103103
exclude = [
104104
"*_assembly_test.cc",
105+
"cxx11_test.cc",
105106
"link_main_test.cc",
106107
],
107108
)
108109
]
109110

111+
cc_test(
112+
name = "cxx11_test",
113+
size = "small",
114+
srcs = ["cxx11_test.cc"],
115+
copts = TEST_COPTS + ["-std=c++11"],
116+
target_compatible_with = select({
117+
"//:windows": ["@platforms//:incompatible"],
118+
"//conditions:default": [],
119+
}),
120+
deps = [
121+
":output_test_helper",
122+
"//:benchmark_main",
123+
],
124+
)
125+
110126
cc_test(
111127
name = "link_main_test",
112128
size = "small",

test/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,18 @@ macro(benchmark_add_test)
7373
endmacro(benchmark_add_test)
7474

7575
# Demonstration executable
76+
77+
compile_benchmark_test_with_main(cxx11_test)
78+
if(DEFINED MSVC)
79+
# MSVC does not really support C++11.
80+
set_property(TARGET cxx11_test PROPERTY CXX_STANDARD 14)
81+
else()
82+
set_property(TARGET cxx11_test PROPERTY CXX_STANDARD 11)
83+
endif()
84+
set_property(TARGET cxx11_test PROPERTY CXX_STANDARD_REQUIRED ON)
85+
set_property(TARGET cxx11_test PROPERTY CXX_EXTENSIONS OFF)
86+
benchmark_add_test(NAME cxx11_test COMMAND cxx11_test --benchmark_min_time=0.01s)
87+
7688
compile_benchmark_test(benchmark_test)
7789
benchmark_add_test(NAME benchmark COMMAND benchmark_test --benchmark_min_time=0.01s)
7890

test/basic_test.cc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ void BM_RangedFor(benchmark::State& state) {
143143
}
144144
BENCHMARK(BM_RangedFor);
145145

146-
#ifdef BENCHMARK_HAS_CXX11
147146
template <typename T>
148147
void BM_OneTemplateFunc(benchmark::State& state) {
149148
auto arg = state.range(0);
@@ -168,8 +167,6 @@ void BM_TwoTemplateFunc(benchmark::State& state) {
168167
BENCHMARK(BM_TwoTemplateFunc<int, double>)->Arg(1);
169168
BENCHMARK(BM_TwoTemplateFunc<double, int>)->Arg(1);
170169

171-
#endif // BENCHMARK_HAS_CXX11
172-
173170
// Ensure that StateIterator provides all the necessary typedefs required to
174171
// instantiate std::iterator_traits.
175172
static_assert(

test/benchmark_test.cc

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,7 @@ BENCHMARK_TEMPLATE2(BM_Sequential, std::vector<int>, int)
131131
->Range(1 << 0, 1 << 10);
132132
BENCHMARK_TEMPLATE(BM_Sequential, std::list<int>)->Range(1 << 0, 1 << 10);
133133
// Test the variadic version of BENCHMARK_TEMPLATE in C++11 and beyond.
134-
#ifdef BENCHMARK_HAS_CXX11
135134
BENCHMARK_TEMPLATE(BM_Sequential, std::vector<int>, int)->Arg(512);
136-
#endif
137135

138136
static void BM_StringCompare(benchmark::State& state) {
139137
size_t len = static_cast<size_t>(state.range(0));
@@ -225,8 +223,6 @@ static void BM_ManualTiming(benchmark::State& state) {
225223
BENCHMARK(BM_ManualTiming)->Range(1, 1 << 14)->UseRealTime();
226224
BENCHMARK(BM_ManualTiming)->Range(1, 1 << 14)->UseManualTime();
227225

228-
#ifdef BENCHMARK_HAS_CXX11
229-
230226
template <class... Args>
231227
void BM_with_args(benchmark::State& state, Args&&...) {
232228
for (auto _ : state) {
@@ -267,8 +263,6 @@ void BM_template1_capture(benchmark::State& state, ExtraArgs&&... extra_args) {
267263
BENCHMARK_TEMPLATE1_CAPTURE(BM_template1_capture, void, foo, 24UL);
268264
BENCHMARK_CAPTURE(BM_template1_capture<void>, foo, 24UL);
269265

270-
#endif // BENCHMARK_HAS_CXX11
271-
272266
static void BM_DenseThreadRanges(benchmark::State& st) {
273267
switch (st.range(0)) {
274268
case 1:

test/cxx11_test.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include "benchmark/benchmark.h"
2+
3+
#if defined(_MSC_VER)
4+
#if _MSVC_LANG != 201402L
5+
// MSVC, even in C++11 mode, dooes not claim to be in C++11 mode.
6+
#error "Trying to compile C++11 test with wrong C++ standard"
7+
#endif // _MSVC_LANG
8+
#else // Non-MSVC
9+
#if __cplusplus != 201103L
10+
#error "Trying to compile C++11 test with wrong C++ standard"
11+
#endif // Non-MSVC
12+
#endif

0 commit comments

Comments
 (0)