Hacker News new | ask | show | jobs
by jcelerier 2197 days ago
> It's also incredibly unsafe and why generics aren't enough. C++, Java, and so on have had generics for ages and with types like the one above, null pointer exceptions are incredibly common.

uh, you'd never get a null-pointer exception in C++ given the type that OP mentioned. Value types in C++ cannot be null (and most things are value types by a large margin).

5 comments

> Value types in C++ cannot be null

They can just not exist. And C++ being C++, dereferencing an empty std::optional is UB. In practice this particular UB often leads to way worse consequences than more "conventional" null-pointer derefs.

Then write your own optional that always checks on dereference or toggle whatever compilation flag enables checking in the standard library you are using.
Instead you can have undefined behaviour in C++.

Don't think get;set is C++, though it breaks encapsulation.

You can also constrain a generic type only to value types in C#:

  class Result<T> where T: struct
  {
  ...
  }
In that case it can't be null with C# either.
Then you can't construct it unless it's successful, no?

A Result<T> that can only contain successful values doesn't seem very useful

You can, it's possible to address "missing values" with a default construct. Example:

  int x = default; // x becomes zero
  T x = default; // x becomes whatever the default value for struct is
Then we're back to accessing that value being an enormous footgun, yes?
Then you can't construct it unless it's successful, no?

A Result<T> that can only contain successful values doesn't seem very useful

No, you just are forced to use methods like foo.UnwrapOr(default_value) to get the Result. Or depending on the language, you get a compile error if you don't handle both possible values of the Result enum in a switch statement or if/else clause.

See for example https://doc.rust-lang.org/std/result/enum.Result.html#method... in rust, https://docs.oracle.com/javase/8/docs/api/java/util/Optional... in Java, and https://en.cppreference.com/w/cpp/utility/optional/value_or in C++.

Who are you replying to? Is any of your elaboration related to this result type?

    class Result<T>
    {
      bool IsSuccess {get; set;}
      string Message {get; set;}
      T Data {get; set;}
    }
Ah you're quite correct.
Yes you can? The equivalent type in C++ is std::expected[1] which doesn't even contain a pointer that could be dereferenced (unless T is a pointer obviously).

[1] unfortunately not standardized yet https://github.com/TartanLlama/expected

Who are you replying to? Is it in any way related to the original comment I replied to and this type?

    class Result<T>
    {
      bool IsSuccess {get; set;}
      string Message {get; set;}
      T Data {get; set;}
    }
I am replying to you and its pretty obviously related to your comment.

You: "C++, Java, and so on have had generics for ages and with types like the one above, null pointer exceptions are incredibly common."

jcelerier: "you'd never get a null-pointer exception in C++ given the type that OP mentioned."

You: "Then you can't construct it unless it's successful, no?"

Me: "The equivalent type in C++ [to what the OP mentioned] is std::expected". It is not possible to get a null-pointer exception with this type and yet you can construct it.

It sounds quite a lot like you took the type the OP posted and changed it in your reply to a different type that isn't standardized yet, do I have that right?
The code the OP posted is not C++. If you translate it to C++ there is no way to get a null pointer exception.

It sounds quite a lot like you're looking to be pointlessly argumentative, do I have that right?

Well, T can be a pointer / reference here.
That wouldn't change anything to Result<T>'s implicit safety properties. "safe + unsafe == unsafe" - to have a meaningful discussion we should focus on the safe part, else it's always possible to bring up the argument of "but you can do ((char*)&whatever)[123] = 0x66;"