googletest icon indicating copy to clipboard operation
googletest copied to clipboard

Enable `PrintTo` template overloads to be defined by the user

Open MakersF opened this issue 3 years ago • 2 comments

Enable PrintTo template overloads to be defined by the user

A user cannot define a template for PrintTo which just takes the type directly. This is because gtest already defines an implementation for the function, which prints the type with the fallback strategy.

This prevents users from providing a PrintTo function like

template<typename T, typename = std::enable_if_t<...>>
void PrintTo(const T&, std::ostream*) { ... }

as it's ambiguous with the PrintTo template defined by gtest.

This change resolves this.

The current behaviour depends on the overload resolution priority for calling the right PrintTo function. This change removes the default implementation of PrintTo, and instead detects whether there is a PrintTo function that can be called with the type. If it exists, it calls that, otherwise it uses the fallback behaviour.

Unfortunately it's not that simple: due to implicit conversions, once the PrintTo (unconstrained) template function is removed, many types will implicitly convert and use one of the other overloads of PrintTo defined by gtest, while before it would have used the unconstrained template, as it was a better match.

To address this, this change checks whether the type would ahve called the unconstrained template, if it existed. In such situations, the fallback behaviour will be used, to remain backward compatible.

To check if the unconstrained template would have been called, such a function is added in a private namespace, and decltype is used to detect which overload would have been called.


Addresses #3674 and it's a more comprehensive solution than #3682

MakersF avatar Dec 05 '21 17:12 MakersF

I tested this change against a codebase with 100k+ tests, and everything compiled (1) and there were no regressions in the results.

(1) one test didn't compile because an implicit copy constructor from a different type is not sfinae friendly (it reports that it's convertible but then a static assert fails the compilation)

MakersF avatar Dec 05 '21 22:12 MakersF

@MakersF, @asoffer: what's the status of this PR? I am also running into https://github.com/google/googletest/issues/3674, and this would be a very desirable enhancement to get in.

hwilliams265 avatar Jun 12 '23 22:06 hwilliams265