google / googletest

GoogleTest - Google Testing and Mocking Framework
https://google.github.io/googletest/
BSD 3-Clause "New" or "Revised" License
33.7k stars 9.98k forks source link

[Bug]: Cannot use structured binding in name generator lambda in INSTANTIATE_TEST_SUITE_P #4492

Closed mankangustafsson closed 3 months ago

mankangustafsson commented 3 months ago

Describe the issue

Fails to compile. See example code below with workarounds

Steps to reproduce the problem

#include "gtest/gtest.h"

#include <string>
#include <tuple>

namespace {
class MyFixture : public testing::TestWithParam<std::tuple<bool, std::string>>
{
 protected:
  void SetUp() override
  {
    std::tie(flag_, name_) = GetParam();
  }

  void TearDown() override
  {

  }

  bool flag_{false};
  std::string name_;
};

TEST_P(MyFixture, TheTest)
{
}

/* It works with this named lambda  
auto MyFixture_NameGen = [](const testing::TestParamInfo<MyFixture::ParamType>& info)
{
  const auto [flag, name] = info.param;
  std::string test_name = flag ? "Flag" : "NoFlag";
  test_name += name;
  return test_name;
};
*/  
INSTANTIATE_TEST_SUITE_P(Combined, MyFixture,
                         testing::Combine(testing::Bool(),
                                          testing::Values("One", "Two")),
                         [](const testing::TestParamInfo<MyFixture::ParamType>& info)
                         {
                           const auto [flag, name] = info.param;
                           // const auto flag = std::get<bool>(info.param);
                           // const auto name = std::get<std::string>(info.param);
                           std::string test_name = flag ? "Flag" : "NoFlag";
                           test_name += name;
                           return test_name;
                         });

} // namespace

int main(int argc, char * argv[])
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

What version of GoogleTest are you using?

c231e6f5b152029dbd5fa4a9e0c04095035aec3f

What operating system and version are you using?

Rocky 9.3

What compiler and version are you using?

gcc 13.1.1 and clang 16.0.6

What build system are you using?

make

all:
    g++ main.cpp -o main -lgtest -lpthread -std=c++17 -Wall -Wextra -pedantic -Wconversion
    @./main

Additional context

Known workarounds, use named lambda or use std::get instead of structured binding No response

dinord commented 3 months ago

This is a general issue with the way macros parse commas as separators, not specific to structured bindings. Wrapping the lambda in parens (()) makes it work as intended: https://godbolt.org/z/4orodv1bq
Please re-open if that doesn't work for some reason.

Thanks for providing a clean repro, I really appreciate that.

mankangustafsson commented 3 months ago

I figured that as well that it was something with macro parsing/expansion. Thanks for the workaround suggestion, works fine.