
On Thu, Dec 19, 2024 at 9:04 AM Vinnie Falco
In C++, free functions which operate on a concrete type or a type which matches named requirements are considered to be part of the public API for that type. std::swap is a good example, this is why cppreference.com lists associated free functions under a section titled "Non-member functions:"
https://en.cppreference.com/w/cpp/container/vector
Good library design means designing for C++. Therefore:
Free functions should be considered equally ergonomic to member functions.
Good encapsulation means giving an algorithm access to as few implementation details as possible. Therefore:
Prefer free functions when an implementation can use only the publicly visible members of a type.
Scott Meyers elaborates on this:
https://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/1844011...
When designing a library you have to assume that the user knows C++. If they don't understand the use of free functions, the solution is that they should educate themselves, not to always use member functions. The free function is better than the member function for several reasons:
1. The implementation only needs to be written once 2. Authors of new containers have less to implement 3. The header file for the containers does not change; no need to include <optional> 4. Multiple free functions can exist, each returning their own optional type, permitting std::optional and boost::optional to co-exist harmoniously. 5. Better encapsulation: the free function does not have access to private members 6.
A common objection to the use of free functions is that the member function is more discoverable, such as in an IDE. This problem is better solved in the IDE, of which there are few, rather than solving it in the container of which there are uncountably many. That is, if someone was to type "u." in the IDE, then the autocomplete feature could show associated free functions in addition to member functions. And when an associated free function is selected, the IDE will change the member function call to become the free function call syntax.
For all the reasons listed above, the free function is preferable to the member function. As this allows the functionality of containers to be extended without imposing additional work on all existing and future container authors. And I do believe that we need better educational resources, so the myth that member functions are somehow more ergonomic can be decisively dismissed.
Sure, that's just another opinion. I'm just relaying my experiences having talked with other developers across multiple languages and programming chats. In reality, I don't think anyone wants `try_find(my_vector)` because you don't normally do try_find on a container like vector. It's important to follow the principle of avoiding over-engineering and under-delivering. The value proposition here is dubious in the first place because it relies on using Boost.Optional in an API and most people aren't huge on using Boost versions of STL components anymore in 2024. - Christian