googletest
googletest copied to clipboard
[FR]: Loosen restrictions on what types are considered containers for matchers
Does the feature exist in the most recent commit?
No.
Why do we need this feature?
There are many types that would be considered containers, but do not expose certain member types or functions that standard containers do.
For instance, std::ranges are not supported because they do not expose the value_type member type (see https://github.com/google/googletest/issues/3403, https://github.com/google/googletest/issues/3564, and https://github.com/google/googletest/issues/4512). Other custom containers do not expose this member type either (see https://github.com/google/googletest/issues/4375). I also have containers that do not expose begin() and end() member functions, but do expose begin(T) and end(T) free functions.
These types currently can't be used with matchers, which means test authors need to jump through hoops to express what they want.
Describe the proposal.
I propose three things:
StlContainerViewgain two additional member types (heretypeis the container type passed in as a template type):
typedef decltype(*begin(std::declval<type>()) value_type;
typedef decltype(std::distance(begin(std::declval<type>()), end(std::declval<type>()))) difference_type;
- All uses of
::value_typeand::difference_typeon the direct container type passed in to the matcher would be changed to use the ones on theStlContainerViewinstead. - All uses of
.begin()and.end()member functions be replaced withbegin(T), andend(T)free functions when the type is not known to be an STL container.
I also softly propose that StlContainerView be renamed to ContainerView since it no longer is tied so closely to the STL. The rest of this proposal does not depend on the renaming, and it could be considered separately, or not at all if that would be preferred.
There are some use of STL containers internally, and there is no need to change their use, though I would not be opposed to also using free functions for those if uniformity was valued.
For this to work, we would need to add using std::begin; and using std::end; to both the ::testing namespace in the matchers header and the ::internal namespace in the internal utils header, otherwise ADL would not work for both STL types and user defined ones.
I would be willing to submit a PR implementing these changes, including tests, if this proposal is accepted.
With the above changes, this test would compile and pass (custom::Array<T> does not define either member functions or types):
TEST(Containers, ElementsAreArray) {
custom::Array<int> custom_array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int> stl_vector = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
EXPECT_THAT(std::ranges::iota_view(0, 10), ::testing::ElementsAreArray(custom_array));
EXPECT_THAT(std::ranges::iota_view(0, 10), ::testing::ElementsAreArray(stl_vector));
EXPECT_THAT(std::ranges::iota_view(0, 10), ::testing::ElementsAreArray(std::ranges::iota_view(0, 10)));
EXPECT_THAT(custom_array, ::testing::ElementsAreArray(custom_array));
EXPECT_THAT(custom_array, ::testing::ElementsAreArray(stl_vector));
EXPECT_THAT(custom_array, ::testing::ElementsAreArray(std::ranges::iota_view(0, 10)));
EXPECT_THAT(stl_vector, ::testing::ElementsAreArray(custom_array));
EXPECT_THAT(stl_vector, ::testing::ElementsAreArray(stl_vector));
EXPECT_THAT(stl_vector, ::testing::ElementsAreArray(std::ranges::iota_view(0, 10)));
}
While I haven't done an exhaustive test suite yet, I fully expect the other matchers that take containers would similarly pass.
Is the feature specific to an operating system, compiler, or build system version?
N/A