Finish cxx version bump (#1948)

* `CMakeLists.txt`: drop hopefully obsolete code

* README.md: update

* Unbreak `BENCHMARK_HAS_CXX11` macro

835365f99a0b9ec338b6748f5ccb96a3673eeccc 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.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fd69060..4f67ff5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -306,17 +306,11 @@
   endif()
 endif(BENCHMARK_USE_LIBCXX)
 
-set(EXTRA_CXX_FLAGS "")
-if (WIN32 AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
-  # Clang on Windows fails to compile the regex feature check under C++11
-  set(EXTRA_CXX_FLAGS "-DCMAKE_CXX_STANDARD=14")
-endif()
-
 # C++ feature checks
 # Determine the correct regular expression engine to use
-cxx_feature_check(STD_REGEX ${EXTRA_CXX_FLAGS})
-cxx_feature_check(GNU_POSIX_REGEX ${EXTRA_CXX_FLAGS})
-cxx_feature_check(POSIX_REGEX ${EXTRA_CXX_FLAGS})
+cxx_feature_check(STD_REGEX)
+cxx_feature_check(GNU_POSIX_REGEX)
+cxx_feature_check(POSIX_REGEX)
 if(NOT HAVE_STD_REGEX AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX)
   message(FATAL_ERROR "Failed to determine the source files for the regular expression backend")
 endif()
diff --git a/README.md b/README.md
index b30e57c..4e73025 100644
--- a/README.md
+++ b/README.md
@@ -50,7 +50,7 @@
 
 ## Requirements
 
-The library can be used with C++03. However, it requires C++14 to build,
+The library can be used with C++11. However, it requires C++17 to build,
 including compiler and standard library support.
 
 _See [dependencies.md](docs/dependencies.md) for more details regarding supported
@@ -190,7 +190,7 @@
 ```bash
 # Example on linux after running the build steps above. Assumes the
 # `benchmark` and `build` directories are under the current directory.
-$ g++ mybenchmark.cc -std=c++14 -isystem benchmark/include \
+$ g++ mybenchmark.cc -std=c++11 -isystem benchmark/include \
   -Lbenchmark/build/src -lbenchmark -lpthread -o mybenchmark
 ```
 
diff --git a/docs/user_guide.md b/docs/user_guide.md
index 3152762..b3c1cce 100644
--- a/docs/user_guide.md
+++ b/docs/user_guide.md
@@ -462,7 +462,7 @@
 
 ### Passing Arbitrary Arguments to a Benchmark
 
-In C++11 it is possible to define a benchmark that takes an arbitrary number
+It is possible to define a benchmark that takes an arbitrary number
 of extra arguments. The `BENCHMARK_CAPTURE(func, test_case_name, ...args)`
 macro creates a benchmark that invokes `func`  with the `benchmark::State` as
 the first argument followed by the specified `args...`.
@@ -563,22 +563,19 @@
   state.SetBytesProcessed(
       static_cast<int64_t>(state.iterations())*state.range(0));
 }
-// C++03
-BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue<int>)->Range(1<<0, 1<<10);
 
-// C++11 or newer, you can use the BENCHMARK macro with template parameters:
+// You can use the BENCHMARK macro with template parameters:
 BENCHMARK(BM_Sequential<WaitQueue<int>>)->Range(1<<0, 1<<10);
 
+// Old, legacy verbose C++03 syntax:
+BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue<int>)->Range(1<<0, 1<<10);
+
 ```
 
 Three macros are provided for adding benchmark templates.
 
 ```c++
-#ifdef BENCHMARK_HAS_CXX11
 #define BENCHMARK(func<...>) // Takes any number of parameters.
-#else // C++ < C++11
-#define BENCHMARK_TEMPLATE(func, arg1)
-#endif
 #define BENCHMARK_TEMPLATE1(func, arg1)
 #define BENCHMARK_TEMPLATE2(func, arg1, arg2)
 ```
@@ -740,12 +737,10 @@
   state.counters["BytesProcessed"] = Counter(state.range(0), benchmark::Counter::kIsIterationInvariantRate, benchmark::Counter::OneK::kIs1024);
 ```
 
-When you're compiling in C++11 mode or later you can use `insert()` with
-`std::initializer_list`:
+You can use `insert()` with `std::initializer_list`:
 
 <!-- {% raw %} -->
 ```c++
-  // With C++11, this can be done:
   state.counters.insert({{"Foo", numFoos}, {"Bar", numBars}, {"Baz", numBazs}});
   // ... instead of:
   state.counters["Foo"] = numFoos;
@@ -1249,7 +1244,7 @@
 
 ## A Faster KeepRunning Loop
 
-In C++11 mode, a ranged-based for loop should be used in preference to
+A ranged-based for loop should be used in preference to
 the `KeepRunning` loop for running the benchmarks. For example:
 
 ```c++
diff --git a/include/benchmark/benchmark.h b/include/benchmark/benchmark.h
index 663953d..c9a758b 100644
--- a/include/benchmark/benchmark.h
+++ b/include/benchmark/benchmark.h
@@ -191,6 +191,14 @@
   TypeName(const TypeName&) = delete;                \
   TypeName& operator=(const TypeName&) = delete
 
+#ifdef BENCHMARK_HAS_CXX17
+#define BENCHMARK_UNUSED [[maybe_unused]]
+#elif defined(__GNUC__) || defined(__clang__)
+#define BENCHMARK_UNUSED __attribute__((unused))
+#else
+#define BENCHMARK_UNUSED
+#endif
+
 // Used to annotate functions, methods and classes so they
 // are not optimized by the compiler. Useful for tests
 // where you expect loops to stay in place churning cycles
@@ -303,6 +311,18 @@
 #endif  // _MSC_VER_
 
 namespace benchmark {
+
+namespace internal {
+#if (__cplusplus < 201402L || (defined(_MSC_VER) && _MSVC_LANG < 201402L))
+template <typename T, typename... Args>
+std::unique_ptr<T> make_unique(Args&&... args) {
+  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+#else
+using ::std::make_unique;
+#endif
+}  // namespace internal
+
 class BenchmarkReporter;
 class State;
 
@@ -472,7 +492,7 @@
 
 // Ensure that the standard streams are properly initialized in every TU.
 BENCHMARK_EXPORT int InitializeStreams();
-[[maybe_unused]] static int stream_init_anchor = InitializeStreams();
+BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
 
 }  // namespace internal
 
@@ -1026,7 +1046,7 @@
 }
 
 struct State::StateIterator {
-  struct [[maybe_unused]] Value {};
+  struct BENCHMARK_UNUSED Value {};
   typedef std::forward_iterator_tag iterator_category;
   typedef Value value_type;
   typedef Value reference;
@@ -1371,7 +1391,7 @@
 inline internal::Benchmark* RegisterBenchmark(const std::string& name,
                                               internal::Function* fn) {
   return internal::RegisterBenchmarkInternal(
-      std::make_unique<internal::FunctionBenchmark>(name, fn));
+      benchmark::internal::make_unique<internal::FunctionBenchmark>(name, fn));
 }
 
 template <class Lambda>
@@ -1379,19 +1399,16 @@
   using BenchType =
       internal::LambdaBenchmark<typename std::decay<Lambda>::type>;
   return internal::RegisterBenchmarkInternal(
-      std::make_unique<BenchType>(name, std::forward<Lambda>(fn)));
+      benchmark::internal::make_unique<BenchType>(name,
+                                                  std::forward<Lambda>(fn)));
 }
 
-#if (!defined(BENCHMARK_GCC_VERSION) || BENCHMARK_GCC_VERSION >= 409)
 template <class Lambda, class... Args>
 internal::Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn,
                                        Args&&... args) {
   return benchmark::RegisterBenchmark(
       name, [=](benchmark::State& st) { fn(st, args...); });
 }
-#else
-#define BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
-#endif
 
 // The base class for all fixture tests.
 class Fixture : public internal::Benchmark {
@@ -1442,13 +1459,14 @@
 #define BENCHMARK_PRIVATE_DECLARE(n)                                           \
   /* NOLINTNEXTLINE(misc-use-anonymous-namespace) */                           \
   static ::benchmark::internal::Benchmark const* const BENCHMARK_PRIVATE_NAME( \
-      n) [[maybe_unused]]
+      n) BENCHMARK_UNUSED
 
 #define BENCHMARK(...)                                                \
   BENCHMARK_PRIVATE_DECLARE(_benchmark_) =                            \
       (::benchmark::internal::RegisterBenchmarkInternal(              \
-          std::make_unique<::benchmark::internal::FunctionBenchmark>( \
-              #__VA_ARGS__, __VA_ARGS__)))
+          benchmark::internal::make_unique<                           \
+              ::benchmark::internal::FunctionBenchmark>(#__VA_ARGS__, \
+                                                        __VA_ARGS__)))
 
 // Old-style macros
 #define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
@@ -1469,11 +1487,12 @@
 //}
 // /* Registers a benchmark named "BM_takes_args/int_string_test` */
 // BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc"));
-#define BENCHMARK_CAPTURE(func, test_case_name, ...)                  \
-  BENCHMARK_PRIVATE_DECLARE(_benchmark_) =                            \
-      (::benchmark::internal::RegisterBenchmarkInternal(              \
-          std::make_unique<::benchmark::internal::FunctionBenchmark>( \
-              #func "/" #test_case_name,                              \
+#define BENCHMARK_CAPTURE(func, test_case_name, ...)     \
+  BENCHMARK_PRIVATE_DECLARE(_benchmark_) =               \
+      (::benchmark::internal::RegisterBenchmarkInternal( \
+          benchmark::internal::make_unique<              \
+              ::benchmark::internal::FunctionBenchmark>( \
+              #func "/" #test_case_name,                 \
               [](::benchmark::State& st) { func(st, __VA_ARGS__); })))
 
 // This will register a benchmark for a templatized function.  For example:
@@ -1484,22 +1503,24 @@
 // BENCHMARK_TEMPLATE(BM_Foo, 1);
 //
 // will register BM_Foo<1> as a benchmark.
-#define BENCHMARK_TEMPLATE1(n, a)                                     \
-  BENCHMARK_PRIVATE_DECLARE(n) =                                      \
-      (::benchmark::internal::RegisterBenchmarkInternal(              \
-          std::make_unique<::benchmark::internal::FunctionBenchmark>( \
-              #n "<" #a ">", n<a>)))
+#define BENCHMARK_TEMPLATE1(n, a)                        \
+  BENCHMARK_PRIVATE_DECLARE(n) =                         \
+      (::benchmark::internal::RegisterBenchmarkInternal( \
+          benchmark::internal::make_unique<              \
+              ::benchmark::internal::FunctionBenchmark>(#n "<" #a ">", n<a>)))
 
-#define BENCHMARK_TEMPLATE2(n, a, b)                                  \
-  BENCHMARK_PRIVATE_DECLARE(n) =                                      \
-      (::benchmark::internal::RegisterBenchmarkInternal(              \
-          std::make_unique<::benchmark::internal::FunctionBenchmark>( \
-              #n "<" #a "," #b ">", n<a, b>)))
+#define BENCHMARK_TEMPLATE2(n, a, b)                                          \
+  BENCHMARK_PRIVATE_DECLARE(n) =                                              \
+      (::benchmark::internal::RegisterBenchmarkInternal(                      \
+          benchmark::internal::make_unique<                                   \
+              ::benchmark::internal::FunctionBenchmark>(#n "<" #a "," #b ">", \
+                                                        n<a, b>)))
 
-#define BENCHMARK_TEMPLATE(n, ...)                                    \
-  BENCHMARK_PRIVATE_DECLARE(n) =                                      \
-      (::benchmark::internal::RegisterBenchmarkInternal(              \
-          std::make_unique<::benchmark::internal::FunctionBenchmark>( \
+#define BENCHMARK_TEMPLATE(n, ...)                       \
+  BENCHMARK_PRIVATE_DECLARE(n) =                         \
+      (::benchmark::internal::RegisterBenchmarkInternal( \
+          benchmark::internal::make_unique<              \
+              ::benchmark::internal::FunctionBenchmark>( \
               #n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>)))
 
 // This will register a benchmark for a templatized function,
@@ -1517,12 +1538,13 @@
 #define BENCHMARK_TEMPLATE1_CAPTURE(func, a, test_case_name, ...) \
   BENCHMARK_CAPTURE(func<a>, test_case_name, __VA_ARGS__)
 
-#define BENCHMARK_TEMPLATE2_CAPTURE(func, a, b, test_case_name, ...)  \
-  BENCHMARK_PRIVATE_DECLARE(func) =                                   \
-      (::benchmark::internal::RegisterBenchmarkInternal(              \
-          std::make_unique<::benchmark::internal::FunctionBenchmark>( \
-              #func "<" #a "," #b ">"                                 \
-                    "/" #test_case_name,                              \
+#define BENCHMARK_TEMPLATE2_CAPTURE(func, a, b, test_case_name, ...) \
+  BENCHMARK_PRIVATE_DECLARE(func) =                                  \
+      (::benchmark::internal::RegisterBenchmarkInternal(             \
+          benchmark::internal::make_unique<                          \
+              ::benchmark::internal::FunctionBenchmark>(             \
+              #func "<" #a "," #b ">"                                \
+                    "/" #test_case_name,                             \
               [](::benchmark::State& st) { func<a, b>(st, __VA_ARGS__); })))
 
 #define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method)        \
@@ -1591,7 +1613,7 @@
 #define BENCHMARK_PRIVATE_REGISTER_F(TestName)           \
   BENCHMARK_PRIVATE_DECLARE(TestName) =                  \
       (::benchmark::internal::RegisterBenchmarkInternal( \
-          std::make_unique<TestName>()))
+          benchmark::internal::make_unique<TestName>()))
 
 // This macro will define and register a benchmark within a fixture class.
 #define BENCHMARK_F(BaseClass, Method)           \
diff --git a/test/BUILD b/test/BUILD
index e3558a9..9a26970 100644
--- a/test/BUILD
+++ b/test/BUILD
@@ -102,12 +102,28 @@
         ["*_test.cc"],
         exclude = [
             "*_assembly_test.cc",
+            "cxx11_test.cc",
             "link_main_test.cc",
         ],
     )
 ]
 
 cc_test(
+    name = "cxx11_test",
+    size = "small",
+    srcs = ["cxx11_test.cc"],
+    copts = TEST_COPTS + ["-std=c++11"],
+    target_compatible_with = select({
+        "//:windows": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    }),
+    deps = [
+        ":output_test_helper",
+        "//:benchmark_main",
+    ],
+)
+
+cc_test(
     name = "link_main_test",
     size = "small",
     srcs = ["link_main_test.cc"],
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index a7e7122..df575d9 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -73,6 +73,18 @@
 endmacro(benchmark_add_test)
 
 # Demonstration executable
+
+compile_benchmark_test_with_main(cxx11_test)
+if(DEFINED MSVC)
+  # MSVC does not really support C++11.
+  set_property(TARGET cxx11_test PROPERTY CXX_STANDARD 14)
+else()
+  set_property(TARGET cxx11_test PROPERTY CXX_STANDARD 11)
+endif()
+set_property(TARGET cxx11_test PROPERTY CXX_STANDARD_REQUIRED ON)
+set_property(TARGET cxx11_test PROPERTY CXX_EXTENSIONS OFF)
+benchmark_add_test(NAME cxx11_test COMMAND cxx11_test --benchmark_min_time=0.01s)
+
 compile_benchmark_test(benchmark_test)
 benchmark_add_test(NAME benchmark COMMAND benchmark_test --benchmark_min_time=0.01s)
 
diff --git a/test/basic_test.cc b/test/basic_test.cc
index c3ac494..b51494b 100644
--- a/test/basic_test.cc
+++ b/test/basic_test.cc
@@ -143,7 +143,6 @@
 }
 BENCHMARK(BM_RangedFor);
 
-#ifdef BENCHMARK_HAS_CXX11
 template <typename T>
 void BM_OneTemplateFunc(benchmark::State& state) {
   auto arg = state.range(0);
@@ -168,8 +167,6 @@
 BENCHMARK(BM_TwoTemplateFunc<int, double>)->Arg(1);
 BENCHMARK(BM_TwoTemplateFunc<double, int>)->Arg(1);
 
-#endif  // BENCHMARK_HAS_CXX11
-
 // Ensure that StateIterator provides all the necessary typedefs required to
 // instantiate std::iterator_traits.
 static_assert(
diff --git a/test/benchmark_test.cc b/test/benchmark_test.cc
index e00f153..141f286 100644
--- a/test/benchmark_test.cc
+++ b/test/benchmark_test.cc
@@ -131,9 +131,7 @@
     ->Range(1 << 0, 1 << 10);
 BENCHMARK_TEMPLATE(BM_Sequential, std::list<int>)->Range(1 << 0, 1 << 10);
 // Test the variadic version of BENCHMARK_TEMPLATE in C++11 and beyond.
-#ifdef BENCHMARK_HAS_CXX11
 BENCHMARK_TEMPLATE(BM_Sequential, std::vector<int>, int)->Arg(512);
-#endif
 
 static void BM_StringCompare(benchmark::State& state) {
   size_t len = static_cast<size_t>(state.range(0));
@@ -225,8 +223,6 @@
 BENCHMARK(BM_ManualTiming)->Range(1, 1 << 14)->UseRealTime();
 BENCHMARK(BM_ManualTiming)->Range(1, 1 << 14)->UseManualTime();
 
-#ifdef BENCHMARK_HAS_CXX11
-
 template <class... Args>
 void BM_with_args(benchmark::State& state, Args&&...) {
   for (auto _ : state) {
@@ -267,8 +263,6 @@
 BENCHMARK_TEMPLATE1_CAPTURE(BM_template1_capture, void, foo, 24UL);
 BENCHMARK_CAPTURE(BM_template1_capture<void>, foo, 24UL);
 
-#endif  // BENCHMARK_HAS_CXX11
-
 static void BM_DenseThreadRanges(benchmark::State& st) {
   switch (st.range(0)) {
     case 1:
diff --git a/test/cxx11_test.cc b/test/cxx11_test.cc
new file mode 100644
index 0000000..db1a993
--- /dev/null
+++ b/test/cxx11_test.cc
@@ -0,0 +1,12 @@
+#include "benchmark/benchmark.h"
+
+#if defined(_MSC_VER)
+#if _MSVC_LANG != 201402L
+// MSVC, even in C++11 mode, dooes not claim to be in C++11 mode.
+#error "Trying to compile C++11 test with wrong C++ standard"
+#endif  //  _MSVC_LANG
+#else   // Non-MSVC
+#if __cplusplus != 201103L
+#error "Trying to compile C++11 test with wrong C++ standard"
+#endif  // Non-MSVC
+#endif
diff --git a/test/donotoptimize_test.cc b/test/donotoptimize_test.cc
index 75db934..5c9a458 100644
--- a/test/donotoptimize_test.cc
+++ b/test/donotoptimize_test.cc
@@ -62,8 +62,6 @@
   BitRef lval = BitRef::Make();
   benchmark::DoNotOptimize(lval);
 
-#ifdef BENCHMARK_HAS_CXX11
   // Check that accept rvalue.
   benchmark::DoNotOptimize(BitRef::Make());
-#endif
 }
diff --git a/test/register_benchmark_test.cc b/test/register_benchmark_test.cc
index e443ab7..1a18814 100644
--- a/test/register_benchmark_test.cc
+++ b/test/register_benchmark_test.cc
@@ -77,7 +77,6 @@
 // Note: GCC <= 4.8 do not support this form of RegisterBenchmark because they
 //       reject the variadic pack expansion of lambda captures.
 //----------------------------------------------------------------------------//
-#ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
 
 void BM_extra_args(benchmark::State& st, const char* label) {
   for (auto _ : st) {
@@ -95,8 +94,6 @@
 const int dummy2 = RegisterFromFunction();
 ADD_CASES({"test1", "One"}, {"test2", "Two"}, {"test3", "Three"});
 
-#endif  // BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
-
 //----------------------------------------------------------------------------//
 // Test RegisterBenchmark with DISABLED_ benchmark
 //----------------------------------------------------------------------------//
@@ -121,14 +118,11 @@
 };
 
 void TestRegistrationAtRuntime() {
-#ifdef BENCHMARK_HAS_CXX11
   {
     CustomFixture fx;
     benchmark::RegisterBenchmark("custom_fixture", fx);
     AddCases({std::string("custom_fixture")});
   }
-#endif
-#ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
   {
     const char* x = "42";
     auto capturing_lam = [=](benchmark::State& st) {
@@ -139,7 +133,6 @@
     benchmark::RegisterBenchmark("lambda_benchmark", capturing_lam);
     AddCases({{"lambda_benchmark", x}});
   }
-#endif
 }
 
 // Test that all benchmarks, registered at either during static init or runtime,