Details
- Reviewers
Mordante ldionne var-const - Group Reviewers
Restricted Project - Commits
- rG667925d45a9e: [libc++] `bitset::operator[] const` should return bool
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
libcxx/include/bitset | ||
---|---|---|
717–722 | Changing the return type is an ABI break. So we can only make this change in the unstable ABI. | |
libcxx/test/std/utilities/template.bitset/bitset.members/index_const.pass.cpp | ||
30 | FYI you can use ASSERT_SAME_TYPE. | |
30 | Since the operator returns different types, maybe it's good to add an explicit type test in |
Thanks for the update, only a few small issues remain.
libcxx/include/__config | ||
---|---|---|
118 | Let's make clear it's about the const overload. | |
libcxx/test/std/utilities/template.bitset/bitset.members/index_const.pass.cpp | ||
31 | Typically we just use the ABI name in our tests, for example in test/std/re/re.const/re.synopt/syntax_option_type.pass.cpp #ifdef _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO // https://llvm.org/PR35967 assert(std::regex_constants::ECMAScript != 0); #else assert(std::regex_constants::ECMAScript == 0); #endif (In the WIP script to test against internal macro's I've whitelisted _LIBCPP_ABI_*.) I actually think the test should be slightly different #if !defined(_LIBCPP_VERSION) || defined(_LIBCPP_ABI_REGEX_CONSTANTS_NONZERO) // https://llvm.org/PR35967 assert(std::regex_constants::ECMAScript != 0); #else assert(std::regex_constants::ECMAScript == 0); #endif |
libcxx/test/std/utilities/template.bitset/bitset.members/index_const.pass.cpp | ||
---|---|---|
15 | I don't think this include is needed since we're using ASSERT_SAME_TYPE macro now. |
What an annoying "extension". The intent is good, however it results in our implementation being clearly non-conforming. I'm in favour of this, and it's a shame that it has to be guarded behind an ABI check.
Can you please add a test that checks for:
typename Container::const_reference cr0 = c[0]; c[0] = 1; assert(cr0 == 1);
at runtime (and a corresponding test case for when const_reference is bool)?
LGTM with changes, thanks!
libcxx/include/__config | ||
---|---|---|
117 | ||
libcxx/test/std/utilities/template.bitset/bitset.members/index_const.pass.cpp | ||
50–59 | Can you add the same test to the non-const operator[] (but you'll only have one assert)? Also, I'd recommend against using #endif // comment since this block is so short -- in this case it's even wrong. |
It looks like we have the same issue in vector<bool> -- can we also fix it there? I think we only need one macro for both, so I'd make that change in this patch. Sorry for the churn.
vector<bool> returns a reference` or a const_reference as expected (https://en.cppreference.com/w/cpp/container/vector/operator_at)
Or am I missing something?
- Address comments
@Mordante I didn't see it either. const_reference should be defined as bool.
libcxx/test/std/containers/sequences/vector.bool/const_reference.pass.cpp | ||
---|---|---|
16 ↗ | (On Diff #419682) | Optional nit: since this test isn't constexpr, it doesn't need to return anything -- unless you expect it to become constexpr at some future point? |
libcxx/test/std/utilities/template.bitset/bitset.members/index_const.pass.cpp | ||
50–59 | This comment doesn't seem to be addressed. |
- Address comments
libcxx/test/std/containers/sequences/vector.bool/const_reference.pass.cpp | ||
---|---|---|
16 ↗ | (On Diff #419682) | This test should become constexpr once we implement P1004R2. |
libcxx/test/std/utilities/template.bitset/bitset.members/index_const.pass.cpp | ||
50–59 | Thanks! I completely forgot to remove the comment. |
libcxx/test/std/containers/sequences/vector.bool/const_reference.pass.cpp | ||
---|---|---|
16 ↗ | (On Diff #419682) | In that case, can you please add a TODO? |
libcxx/test/std/containers/sequences/vector.bool/const_reference.pass.cpp | ||
---|---|---|
16 ↗ | (On Diff #419682) | I don't think adding a TODO makes a lot of sense here. When implementing P1004R2 almost every single file inside vector.bool and vector have to be changed anyways. |
LGTM once CI is passing. Please ping me again if it ends up being more complicated than just removing the now redundant insert() method. Thanks for the cleanup!
libcxx/include/vector | ||
---|---|---|
2086 ↗ | (On Diff #419939) | To fix the CI issue, I think you'll need to remove the additional insert(...) method we have that takes a const_reference. It's not in the spec, and it was probably just provided to make it work with our non-conforming const_reference type. You should also survey for other places where we take a const_reference and make sure that those methods are all part of the spec -- it's possible that we have other cases like this, and we might not catch them (I don't know how good our coverage is for std::vector<bool>). |
libcxx/test/std/utilities/template.bitset/bitset.members/index.pass.cpp | ||
61–64 |
- Remove insert overload
@ldionne I just removed the insert overload, but it seems it was never defined, so I remove it in ABIv1 too.
LGTM, but I would really like to investigate removing const_reference from bitset altogether, since there isn't one in the Standard. It's a rather bad API to provide a typedef called const_reference that isn't a reference, and in fact it leads to the very confusion we are removing an extension for. I'd rather break people's source (considering there probably isn't too many users of bitset::const_reference out there) than give them an API that is both non-standard and error-prone.
Is it intentional that this leaves std::vector<bool>::const_iterator::reference as the class type? We're seeing some breakage in absl due to that.
We're also seeing some breakage due to the result of std::bitset::operator[]() const no longer being convertible to std::bitset::const_reference, which would at least have been easier to understand if the const_reference typedef were removed entirely.
FWIW, the broken code looks roughly like this:
struct NumberLike { // ... template<typename T> NumberLike(T) requires std::is_arithmetic_v<T>; NumberLike(std::vector<bool>::reference); NumberLike(std::vector<bool>::const_reference); } void Consume(NumberLike); template<typename Container> void ConsumeAll(const Container &c) { for (const auto &v : c) Consume(v); }
This works if vector<bool>::const_reference and vector<bool>::const_iterator::reference are the same type, but if the iterator produces the class type but vector<bool>::const_reference is simply bool then the Consume call fails.
I just uploaded D123851 for the vector part. I'm planning to look into removing bitset::const_reference, but since it shouldn't exist, nobody should use it anyways.