This is basically just for consistency, it's quite strange to see
multiple AK container types next to each other, some with and some
without the namespace prefix - we're 'using AK::Foo;' a lot and should
leverage that. :^)
A new operator, operator""sv was added as of C++17 to support
string_view literals. This allows string_views to be constructed
from string literals and with no runtime cost to find the string
length.
See: https://en.cppreference.com/w/cpp/string/basic_string_view/operator%22%22sv
This change implements that functionality in AK::StringView.
We do have to suppress some warnings about implementing reserved
operators as we are essentially implementing STL functions in AK
as we have no STL :).
(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED)
Since all of these checks are done in release builds as well,
let's rename them to VERIFY to prevent confusion, as everyone is
used to assertions being compiled out in release.
We can introduce a new ASSERT macro that is specifically for debug
checks, but I'm doing this wholesale conversion first since we've
accumulated thousands of these already, and it's not immediately
obvious which ones are suitable for ASSERT.
This is an improved version of WrapperGenerator's snake_name(), which
seems like the kind of thing that could be useful elsewhere but would
end up getting duplicated - so let's add this to AK::String instead,
like to_{lowercase,uppercase}().
These don't do short-circuit evaluation, and so I ran into some
some very subtle side-effects when converting code to DistinctNumeric.
In code like this:
MyDistinctNumeric n;
if (n && check_thing(n))
return;
There would be no short-circuit evaluation if the return type of
check_thing() was implicitly convertible to MyDistinctNumeric.
Ran into this while making Ext2FS::GroupIndex a DistinctNumeric.
- The change to quick_sort requires SimpleIterator to support
assignment.
- Rename quick_sort to single_pivot_quick_sort to make it easier
to choose a specific implementation (not based on signature).
- Ensure single_pivot_quick_sort does not copy the pivots
- Expand sorts_without_copy test case to cover both single and dual
pivot implementations.
Problem:
- Access to the underlying type is not provided. This limits
metaprogramming and usage in function templates.
Solution:
- Provide public access to the underlying type.
- Add test to ensure the underlying type is accessible.
Problem:
- Raw loops are often written to validate that any values in a
container meet a predicate, but raw loops are not as expressive as
functions implementing well-named algorithms and are error-prone.
Solution:
- Implement a very generic form of `any_of`.
This API was a mostly gratuitous deviation from POSIX that gave up some
portability in exchange for avoiding the occasional strlen().
I don't think that was actually achieving anything valuable, so let's
just chill out and have the same open() API as everyone else. :^)
Problem:
- Many constructors are defined as `{}` rather than using the ` =
default` compiler-provided constructor.
- Some types provide an implicit conversion operator from `nullptr_t`
instead of requiring the caller to default construct. This violates
the C++ Core Guidelines suggestion to declare single-argument
constructors explicit
(https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c46-by-default-declare-single-argument-constructors-explicit).
Solution:
- Change default constructors to use the compiler-provided default
constructor.
- Remove implicit conversion operators from `nullptr_t` and change
usage to enforce type consistency without conversion.
Problem:
- The implementation of `find` is coupled to the implementation of
`SinglyLinkedList`.
Solution:
- Decouple the implementation of `find` from the class by using a
generic `find` algorithm.
Problem:
- The implementation of `find` is coupled to the implementation of
`DoublyLinkedList`.
- `append` and `prepend` are implemented multiple times so that
r-value references can be moved from into the new node. This is
probably not called very often because a pr-value or x-value needs
to be used here.
Solution:
- Decouple the implementation of `find` from the class by using a
generic `find` algorithm.
- Make `append` and `prepend` be function templates so that they can
have binding references which can be forwarded.
Problem:
- The implementation of `find` is coupled to the implementation of `Vector`.
- `Vector::find` takes the predicate by value which might be expensive.
Solution:
- Decouple the implementation of `find` from `Vector` by using a
generic `find` algorithm.
- Change the name of `find` with a predicate to `find_if` so that a
binding reference can be used and the predicate can be forwarded to
avoid copies.
- Change all the `find(pred)` call sites to use `find_if`.
Problem:
- `find` is implemented inside of each container. This coupling
requires that each container needs to individually provide `find`.
Solution:
- Decouple the `find` functionality from the container. This allows
provides a `find` algorithm which can work with all
containers. Containers can still provide their own `find` in the
case where it can be optimized.
- This also allows for searching sub-ranges of a container rather than
the entire container as some of the container-specific member
functions enforced.
Note:
- @davidstone's talk from 2015 C++Now conference entitled "Functions
Want to be Free" encourages this style:
(https://www.youtube.com/watch?v=_lVlC0xzXDc), but it does come at
the cost of composability.
- A logical follow-on to this is to provide a mechanism to use a
short-hand function which automatically searches the entire
container. This could automatically use the container-provided
version if available so that functions which provide their own
optimized version get the benefit.
Problem:
- Clang ToT fails to build `AK/Tests/TestTypeTraits.cpp` because
`nullptr_t` is missing the `std` namespace qualifier.
Solution:
- Prepend the namespace qualifier.
Add requires clauses to constraints on InputStream and OutputStream
operator<< / operator>>. Make the constraint on String::number a
requires clause instead of SFINAE. Also, fix some unecessary IsSame in
Trie where specialized traits exist for the given use cases.
Use TypeLists to add test for IsIntegral, IsFloatingPoint, IsVoid,
IsNullPointer, IsArithmetic, IsFundamental, and AddConst type traits.
More can "easily" be added once the TypeList and macro magic is squinted
at for long enough :).
I ran into this exact but at least twenty times in Serenity alone. The
C++ Standard dictates that 'unsigned long' and 'unsigned long long' are
distinct types even though on most platforms they are usually both 64
bit integers.
Also it wasn't possible to evaluate IsIntegral<T> for types that were
not integers since it used MakeUnsigned<T> internally.
Problem:
- C functions with no arguments require a single `void` in the argument list.
Solution:
- Put the `void` in the argument list of functions in C header files.
Problem:
- File globbing is performed at the time of build system
generation. Any files which are not there at that time are not
included. So, when a new file is added it is not built unless the
build system is recreated.
Solution:
- Remove globbing from AK/Tests directory in favor of explicitly
listing the files.
Problem:
- `(void)` simply casts the expression to void. This is understood to
indicate that it is ignored, but this is really a compiler trick to
get the compiler to not generate a warning.
Solution:
- Use the `[[maybe_unused]]` attribute to indicate the value is unused.
Note:
- Functions taking a `(void)` argument list have also been changed to
`()` because this is not needed and shows up in the same grep
command.
This uses the KMP algorithm to implement the search.
Also replaces the slow route of the normal memmem() with KMP, which
should be fairly faster (O(n + m) as opposed to O(n * m)) :^)
Fixes a regression introduced by 5c1b3ce. The commit description there
asserts that the changes allow calling will_be_destroyed and
one_ref_left, which are not required to be const qualified. The
implementation in fact does require the methods to be const qualified,
because we forgot to add the const_cast inside the decltypes :^)
Problem:
- It is difficult to refactor because there are no tests to bind the
functionality.
- Arguments are not forwarded correctly to the constructor.
Solution:
- Add tests.
- Change constructor to take forwarding references.