Skip to content

examples/parameterized.cpp: overload of format_test_parameter is ineffective #683

@asiz

Description

@asiz

The intended behaviour is documented in the comments:

  // Modifying test names when using alternative syntax
  // When using the alternative syntax, the test names are extended based on the
  // test parameters (to ensure uniqueness). Here, for simple built-in types,
  // the parameter value is printed, while other types are simply enumerated.
  // Without the `format_test_parameter` overload above, the test names for the
  // test below would be:
  //   "parameterized test names (42, int)"
  //   "parameterized test names (true, bool)"
  //   "parameterized test names (3rd parameter, std::complex<double>)"
  // However, since the overload for std::complex is available, the third test name becomes:
  //   "parameterized test names (1.5+2i, std::complex<double>)"
 "parameterized test names"_test = []<class TArg>([[maybe_unused]] TArg arg) {
    expect(true);
  } | std::tuple{42, true, std::complex{1.5, 2.0}};

However, modifying the test with expect(false), the report is

Running test "parameterized test names (3rd parameter, std::complex<double>)"... FAILED
in: parameterized.cpp:90 - test condition:  [false]

That is, the complex value 1.5+2i is not printed. As far as I checked (I am using g++ -std=c++23/26), the behaviour is the same since the commit e131611f that first introduced the example. The critical piece of code is the intended overload:

namespace boost::inline ext::ut {

namespace {
template <std::floating_point F>
std::string format_test_parameter(const std::complex<F>& arg,
                                  [[maybe_unused]] const int counter) {
  std::ostringstream oss;
  oss << arg.real() << '+' << arg.imag() << 'i';
  return oss.str();
}
}  // namespace

}  // namespace boost::inline ext::ut

The overload is ineffective because it is not accessible at the point of usage (inside ut.hpp). I could reproduce the intended result in a few ways:

  1. By changing the overload to a full template specialization, and removing the anonymous namespace.
  2. *By moving the overload to the std namespace.
  3. By using a custom type or template in a custom namespace, and including the overload there.

Option 1 works because we are no longer overloading, but specializing the already declared template.
Option 2* works because of ADL, but is illegal.
Option 3 works because of ADL, and is legal.

It seems the example should be fixed. Am I correct? What do you think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions