Paymahn Moghadasian
Paymahn Moghadasian

Reputation: 10329

How to use macro arguments in call to another macro?

I'd like to be able to create a macro which calls other macros. The macro I'd like to call is the Benchmark macro from folly.

Ultimately, I'd like to have a bunch of macros that look like:

BENCHMARK(filter_10_vector_1_filter, n) { ... }
BENCHMARK(filter_10_set_1_filter, n) { ... }
BENCHMARK(filter_10_vector_2_filter, n) { ... }
BENCHMARK(filter_10_set_2_filter, n) { ... }
BENCHMARK(filter_10_vector_3_filter, n) { ... }
BENCHMARK(filter_10_set_3_filter, n) { ... }
... all the way to 10_filter

BENCHMARK(filter_100_vector_1_filter, n) { ... }
BENCHMARK(filter_100_set_1_filter, n) { ... }
... all the way to 10_filter

I tried creating a macro that looks like:

#define CreateBenchmark(numElements, numFilters) \
  BENCHMARK(filter_##numElements_vector_##numFilters_filters, n) { ... } \
  BENCHMARK_RELATIVE(filter_##numElements_set_##numFilters_filters, n) { ... }

CreateBenchmark(10, 2);

which would hopefully halve the number of macros I need to write. However, the ##numElements and ##numFilters substitutions are not happening as I hoped. The result of the CreateBenchmark(10, 2) call is

============================================================================
FilterWithSetBenchmark.cpp  relative  time/iter  iters/s
============================================================================
filter_numElements_vector_numFilters_filters               264.35us    3.78K
filter_numElements_set_numFilters_filters         99.93%   264.54us    3.78K
============================================================================

I was expecting filter_10_vector_2_filters and fitler_10_set_2_filters. Is there a way to sub the values supplied to the CreateBenchmark macro into the values passed to the BENCHMARK and BENCHMARK_RELATIVE calls?

As a bonus, can my CreateBenchmark macro use a for loop to create all of the XX_filters so that one call to CreateBenchmark generates 20 macro calls (10 for _vector_ and 10 for _set_)?

Upvotes: 5

Views: 1238

Answers (3)

Mad Physicist
Mad Physicist

Reputation: 114290

You forgot the trailing concatenation operator ##:

#define CreateBenchmark(numElements, numFilters) \
  BENCHMARK(filter_ ## numElements ## _vector_ ## numFilters ## _filters, n) { ... } \
  BENCHMARK_RELATIVE(filter_ ## numElements ## _set_ ## numFilters ## _filters, n) { ... }

Think of ## as the string concatenation operator just like + in Java or Python.

Upvotes: 4

Paymahn Moghadasian
Paymahn Moghadasian

Reputation: 10329

Figured it out by accident. My create macro function needed more #. Here's the new one:

#define CreateBenchmark(numElements, numFilters) \
  BENCHMARK(filter_##numElements##_vector_##numFilters##_filters, n) { ... } \
  BENCHMARK_RELATIVE(filter_##numElements##_set_##numFilters##_filters, n) { ... }

Basically, what I want subbed needs to be completely enclosed in double #. Went from ##numElements to ##numElements##. Similarly for numFilters.

Upvotes: 1

Puppy
Puppy

Reputation: 146910

You can use __VA_ARGS__ to represent the macro arguments.

Upvotes: -2

Related Questions