[FR]: Loosen restrictions on what types are considered containers for matchers
ChewyGumball opened this issue · comments
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 #3403, #3564, and #4512). Other custom containers do not expose this member type either (see #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:
StlContainerView
gain two additional member types (heretype
is 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_type
and::difference_type
on the direct container type passed in to the matcher would be changed to use the ones on theStlContainerView
instead. - 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