google / google/googletest

Enable user-defined templated PrintTo to not be ambiguous

Open
#3,674 5 comments 1 reaction 1 assignee Claimed by @asoffer View on GitHub
enhancement
Dominant language
C++
Stars
39.5k
Forks
10.9k
Avg merge
6d 13h
Merged PRs (30d)
1

Description

I'm proposing to make the following compile

```c++
namespace user {

struct A {};

template>
void PrintTo(const T& t, std::ostream* os) { ... }
}

testing::PrintToString(user::A{});
```

which currently fails due to an ambiguous overload with the `PrintTo `defined in gtest.

**Does the feature exist in the most recent commit?**

No

**Why do we need this feature?**

Enable to define `PrintTo` methods for templates, using SFINAE to constrain them on the right type.

Typical case:

Library authors can define a concept (intended as an set of requirements a type must satisfy) that users of the library need to implement.
Given this concept, they might be able to print the type in an effective way.
It would be good to enable the library to define a `PrintTo` that all the types implementing the concept can use.

The possible workarounds are

1. Create a wrapper type which defines the `operator<<`. This cannot be used for `final` types (my current situation). It also requires the user to wrap every object into such wrapper.
2. Define a `PrintTo` for each type. The library author not be able to, if the type is created by the user. For the user, this might be very tiresome if there are many types
3. Use C++20, using a requires clause on the function. Since require clauses are considered more specific than unconstrained templates, this fixes the ambiguous problem. Unfortunately C++20 won't be available in production to many people for quite a while.

See https://stackoverflow.com/questions/25146997/teach-google-test-how-to-print-eigen-matrix for a user struggling with the ambiguity of the template.

Google itself has this problem: protobuf printer is integrated inside google test, I suspect because it's not possible to add it as an external component, since it does concept detection on any type.

**Describe the proposal**

Resolve the template ambiguity.

It can be done by removing the `PrintTo` (from https://github.com/google/googletest/blob/1b18723e874b256c1e39378c6774a90701d70f7a/googletest/include/gtest/gtest-printers.h#L438 ), and change the `UniversalPrinter` to detect whether a valid `PrintTo` function exists, and call that if so, otherwise call the fallback.
Special care needs to be taken because of implicit conversions that would make the `PrintTo` function selected when currently the fallback is used.

I have managed to get this to compile and pass all the existing tests, and I'm currently testing it against a very large code base to ensure it's a backward compatible change.

I'm looking to upstream the change if there is interest.

**Is the feature specific to an operating system, compiler, or build system version?**

No

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.