Merge pull request #101 from google/variadic_macros

Add variadic macro for BENCHMARK_TEMPLATE in c++11 and beyond.
diff --git a/README.md b/README.md
index 4acd1ff..553e34a 100644
--- a/README.md
+++ b/README.md
@@ -130,6 +130,18 @@
 BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue<int>)->Range(1<<0, 1<<10);
 ```
 
+Three macros are provided for adding benchmark templates.
+
+```c++
+#if __cplusplus >= 201103L // C++11 and greater.
+#define BENCHMARK_TEMPLATE(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)
+```
+
 In a multithreaded test, it is guaranteed that none of the threads will start
 until all have called KeepRunning, and all will have finished before KeepRunning
 returns false. As such, any global setup or teardown you want to do can be
diff --git a/include/benchmark/benchmark_api.h b/include/benchmark/benchmark_api.h
index a4be2da..0982e93 100644
--- a/include/benchmark/benchmark_api.h
+++ b/include/benchmark/benchmark_api.h
@@ -445,7 +445,7 @@
 // BENCHMARK_TEMPLATE(BM_Foo, 1);
 //
 // will register BM_Foo<1> as a benchmark.
-#define BENCHMARK_TEMPLATE(n, a)                             \
+#define BENCHMARK_TEMPLATE1(n, a)                            \
   static ::benchmark::internal::Benchmark* BENCHMARK_CONCAT( \
       _benchmark_, n, __LINE__) BENCHMARK_UNUSED =           \
       (new ::benchmark::internal::Benchmark(#n "<" #a ">", n<a>))
@@ -455,6 +455,16 @@
       _benchmark_, n, __LINE__) BENCHMARK_UNUSED =           \
       (new ::benchmark::internal::Benchmark(#n "<" #a "," #b ">", n<a, b>))
 
+#if __cplusplus >= 201103L
+#define BENCHMARK_TEMPLATE(n, ...) \
+  static ::benchmark::internal::Benchmark* BENCHMARK_CONCAT( \
+      _benchmark_, n, __LINE__) BENCHMARK_UNUSED =           \
+      (new ::benchmark::internal::Benchmark(                 \
+        #n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>))
+#else
+#define BENCHMARK_TEMPLATE(n, a) BENCHMARK_TEMPLATE1(n, a)
+#endif
+
 // Helper macro to create a main routine in a test that runs the benchmarks
 #define BENCHMARK_MAIN()                             \
   int main(int argc, const char** argv) {            \
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index bc62f43..8fdb6f3 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -2,6 +2,10 @@
 
 find_package(Threads REQUIRED)
 
+set(CXX03_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-std=c++11" "-std=c++03" CXX03_FLAGS "${CXX03_FLAGS}")
+string(REPLACE "-std=c++0x" "-std=c++03" CXX03_FLAGS "${CXX03_FLAGS}")
+
 macro(compile_benchmark_test name)
   add_executable(${name} "${name}.cc")
   target_link_libraries(${name} benchmark ${CMAKE_THREAD_LIBS_INIT})
@@ -23,3 +27,8 @@
 
 compile_benchmark_test(basic_test)
 add_test(basic basic_test)
+
+compile_benchmark_test(cxx03_test)
+set_target_properties(cxx03_test
+    PROPERTIES COMPILE_FLAGS "${CXX03_FLAGS}")
+add_test(cxx03 cxx03_test)
diff --git a/test/benchmark_test.cc b/test/benchmark_test.cc
index 82f3f99..f5abe61 100644
--- a/test/benchmark_test.cc
+++ b/test/benchmark_test.cc
@@ -121,6 +121,10 @@
 }
 BENCHMARK_TEMPLATE2(BM_Sequential, std::vector<int>, int)->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.
+#if __cplusplus >= 201103L
+BENCHMARK_TEMPLATE(BM_Sequential, std::vector<int>, int)->Arg(512);
+#endif
 
 static void BM_StringCompare(benchmark::State& state) {
   std::string s1(state.range_x(), '-');
diff --git a/test/cxx03_test.cc b/test/cxx03_test.cc
new file mode 100644
index 0000000..56779d6
--- /dev/null
+++ b/test/cxx03_test.cc
@@ -0,0 +1,31 @@
+
+#include <cstddef>
+
+#include "benchmark/benchmark.h"
+
+#if __cplusplus >= 201103L
+#error C++11 or greater detected. Should be C++03.
+#endif
+
+void BM_empty(benchmark::State& state) {
+    while (state.KeepRunning()) {
+        volatile std::size_t x = state.iterations();
+        ((void)x);
+    }
+}
+BENCHMARK(BM_empty);
+
+template <class T, class U>
+void BM_template2(benchmark::State& state) {
+    BM_empty(state);
+}
+BENCHMARK_TEMPLATE2(BM_template2, int, long);
+
+template <class T>
+void BM_template1(benchmark::State& state) {
+    BM_empty(state);
+}
+BENCHMARK_TEMPLATE(BM_template1, long);
+BENCHMARK_TEMPLATE1(BM_template1, int);
+
+BENCHMARK_MAIN()