Search code examples
c++c-preprocessorgoogletest

Lambda with structured bindings inside macro call


This may be related to How to correctly forward structured binding arguments in a macro , but I feel the real problem is not the same, so may have a different solution.

I want to pass a lambda as a name generator inside gtest's INSTANTIATE_TEST_SUITE_P. This works well until I try to use structured bindings, whose comma makes the preprocessor think it gets split into separate arguments.

using param = std::tuple<int, int>;

// This works
INSTANTIATE_TEST_SUITE_P(
    instance, suite, cases,
    [](const testing::TestParamInfo<param>& info) {
        return std::string(std::get<0>(info.param)
            + "_to_" + std::string(std::get<1>(info.param));
    }
);

// This also works
static constexpr auto name = [](const testing::TestParamInfo<param>& info) {
    const auto [a, b] = info.param;
    return std::string(a) + "_to_" + std::to_string(b);
};

INSTANTIATE_TEST_SUITE_P(
    instance, suite, cases, name
);

// But this does not compile
INSTANTIATE_TEST_SUITE_P(
    instance, suite, cases,
    [](const testing::TestParamInfo<param>& info) {
        const auto [a, b] = info.param;
        return std::string(a) + "_to_" + std::to_string(b);
    }
);

I know that in some cases like template arguments, the comma can be protected from preprocessor by an extra set of parentheses. Can the same be done here? I tried placing parentheses around the structured binding, but it did not compile either.


Solution

  • Answered in comments: putting entire lambda in parentheses solves the issue.

    INSTANTIATE_TEST_SUITE_P(
        instance, suite, cases,
        ([](const testing::TestParamInfo<param>& info) {
            const auto [a, b] = info.param;
            return std::string(a) + "_to_" + std::to_string(b);
        })
    );