This is not even remotely true. Let's say you have:
std::unique_ptr<foo> m_foo;
How do you pass that into a function that can receive a pointer to foo, but does not require it? The only way to do so is to declare the function to take a foo* and pass it m_foo.get()
In summary, * will never be deprecated until C++ has support for something along the lines of Rust's borrowing and lifetimes.
As you can see, there's a tradeoff involved. On the one hand, you get crystal clear, descriptive type: std::optional<std::reference_wrapper<foo>> is clearly an optional reference to foo.
On the other hand, using it is absolutely atrocious: you have to write borrowed->get().thingamajig as opposed to borrowed->thingamajig, and std::make_optional(std::ref(*(owned.get()))) as opposed to owned.get()
Does it work? Absolutely. Is it crystal clear? Indisputably so. Will it deprecate raw pointers? I really, really doubt it, but that's just my opinion.
> How do you pass that into a function that can receive a pointer to foo, but does not require it?
Same as you would have a function that can receive an `int` but does not require it. Or a receive a `std::vector` but does not require it.
I surmise that you mean "how do you pass any value (pointer or otherwise) into a function that can receive a value but does require it". And I surmise you have before used pointer indirection to pass that value because it has a conventional sentinel value of 0/NULL/nullptr.
You are correct in that optional values did not have a standardized solution, until C++17 std::optional.
If you don't have C++17, I recommend one of the equivalent third-party implementations:
> In any case, you can use std::optional<std::reference_wrapper<MyVeryLargeType>>.
I would frankly give a negative code review to anyone who would do that.
You go from e.g.
void my_function(T* foo, T* bar, int baz)
{
// ...
foo->stuff(bar, baz);
}
to
void my_function(std::optional<std::reference_wrapper<T>> foo, std::optional<std::reference_wrapper<T>> bar, int baz)
{
// ...
foo->get().call(&bar->get(), z);
}
this also has more overhead (sizeof(std::optional<std::reference_wrapper<T>>) is twice the size of T* ),
and let's not even start talking about calling conventions and the compile time cost of having to include both <functional> and <optional> everywhere.
heh, to say that I originally wrote if(foo) and then replaced it by //... because that was not the point.
Also, dereferencing an unset optional is also UB, so it would segfault all the same given the same preconditions.
> The first has no such indication, except hopefully some human-readable comment that the pointer may be NULL.
I don't understand. If the parameter was not meant to be sometimes null it would be a reference; not a pointer.
The fact that a pointer is used is the "this may be null" indication.
Not formally, but as you were responding to a comment on style: indeed, you don't really need * that often; there are more powerful, safer options in most cases.
But C++ is a systems programming language and * is still quite useful.