8 ms·
What's really weird to me is not that C++ has a unit type and picked a weird name for it (that's just C++). The weird thing is how many unit types it has: - st
by tpolzer 2y ago
What's really weird to me is not that C++ has a unit type and picked a weird name for it (that's just C++). The weird thing is how many unit types it has:
- std::nullopt_t
- std::nullptr_t
- std::monostate
- std::tuple<>
And I'm sure there's more.
- bombela 2y agoWhat about "void"?
- tines 2y agovoid isn’t a unit type (inhabited by a single value), it’s a “bot” type, I.e. no values inhabit it.
- remram 2y agoThat doesn't seem right to me. I can define a function returning "void", and it can terminate. I would expect that a function returning an uninhabited type can never complete.
- jey 2y agoAnd “bot” refers to the bottom type: https://en.wikipedia.org/wiki/Bottom_type https://en.wikipedia.org/wiki/Bottom_type
- gpderetta 2y agovoid is the unit type. The fact that it is not constructible is a wart of the language, inherited from C. It would be easy to fix and would simplify a significant amount of generic code. A function returning bottom cannot return, yet void foo() {} can. In fact it can even return the result of calling other void functions: void bar() { } void foo(){ return bar();} In generic code void is usually internally replaced by a proper, regular void_t unit type and converted back to void at boundaries for backward compatibility. [[noreturn]] void bar(); would be a candidate for a bottom-returning function, except that [[noreturn]] isn't really part of the type system.
- tines 2y agoThat's a good point. Maybe one could argue that rather than the unit type not being constructible, the wart of C is that functions that return "bot" can still "finish executing without returning". I would almost rather argue that void is indeed the "bot" type, and a function marked with a void return type shouldn't be said to "return void;" rather we should say that it's an overloaded syntax that means the function has no return value at all. Same for "return bar()" there, that's just a false-friend of the syntax for returning a value, just syntactic sugar for "bar(); return;".
- MathMonkeyMan 2y agoI ran into this recently writing some C++20 coroutines. The protocol for delivering values from a coroutine that was previously suspended has two flavors: one for values and one for void. My initial draft just implemented the value version and used a struct VoidTODO {} where void should be. It's too late now. void pointers are used as a pun to mean "type wildcard." If void were a real thing that could have a size and address, that wouldn't work anymore.
- rerdavies 2y agoYes!! Been there done that. Two flavors of EVERYTHING: one to deal with functions that return values; and one to deal with void functions. It's awful.
- sixfiveotwo 2y ago> void is the unit type. The fact that it is not constructible is a wart of the language, inherited from C. > A function returning bottom cannot return, yet void foo() {} can. Or you could say it the other way, that it is the bottom type, and the fact that it can be used as the unit type for returned values is a wart of the language. Furthermore, void* isn't a pointer of the unit type, it's a type for pointers to undefined/unspecified value types.
- LegionMammal978 2y agoA pointer to the bottom type would make even less sense as an interpretation for void *, since such a pointer couldn't possibly point to any initialized value.
- kazinator 2y agovoid is not a subtype of all types, though. C and C++ don't have a type spindle, where void would be at the bottom. Only C++ has the concept of subtype, only in the class system, and the C++ class system doesn't have a bottom type; there is no bottom class that is a base for all the others. void is not a proper type; it's just a hack shoehorned into a convenient spot in the type system. Which is why the C++ people have to invent this whole zoo of other things. If void were a type, then, for starters, "return x;" would be syntactically valid in a function returning void. (Only, no possible x would satisfy the type system, so there would have to be a diagnosable rule violation in that regard.) A function returning void does not return a type. It doesn't return anything; it is a procedure invoked for side effects. The same situation could be achieved in other ways, like having a procedure keyword instead of void. The (void) parameter list is another example of void just being a hack. It was introduced in ISO C, and then C++ adopted it for compatibility. The 2023 draft of ISO C finally made () equivalent to (void), though it will probably take many decades for (void) to disappear.
- deleted 2y ago[deleted]
- gpderetta 2y ago> C and C++ don't have a type spindle, where void would be at the bottom. Only C++ has the concept of subtype, only in the class system, and the C++ class system doesn't have a bottom type; there is no bottom class that is a base for all the others. A bottom type is not the base of all other types. > void is not a proper type; it's just a hack shoehorned into a convenient spot in the type system. It is a type, but it is not Regular and it is incomplete. 'return x;' is invalid in a void-returning function because it doesn't type check. 'return void()' or 'return (void)0;' or 'return void_returning_function();' are all valid because they type check. Making void regular has been proposed multiple times [1]. It is a relatively simple extension but nobody that cares has the time to carry it through standardization. [1] https://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0146r1.html https://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0146r1...
- kazinator 2y ago
- omnicognate 2y agoThe distinct types are the whole point. You wouldn't want a std::tuple<> to be implicitly convertible to a std::optional<T> (for arbitrary T), and std::nullptr_t exists to be the type of nullptr, which captures the conversion behaviours appropriate for null pointer literals and has nothing to do with the variant use case std::monostate exists to serve.
- mmaniac 2y agoWhy wouldn't you want std::tuple<> to be the same as std::monostate, though? In many languages with a proper unit type such as Haskell and Rust, the zero tuple is the unit type.
- tpolzer 2y agoIf there was a std::unit_t and it was implicitly convertible to optional, tuple and pointer, I don't think that would be worse in terms of usability at all (maybe worse in readability for people who haven't heard of a 'unit' type). As for the std::variant use case, using std::monostate is only a matter of convention there. You could use any of the other unit types just the same.
- omnicognate 2y agostd::monostate is explicitly provided for use with std::variant. It's in the <variant> header. Sometimes people use it for other things, but that's really an abuse, especially given defining your own type suitable for such cases is typically as simple as `struct mytype{};`. Using one type to represent empty literals for optional, tuple and pointer types, implicitly convertible to all of them, would make the compiler accept many obviously accidental constructs. In a world where the maintainers of C++ are trying their hardest to make the language safer what conceivable benefit would there be?
- gumby 2y agoThen you're basically back to "anything can convert back and forth with void " -- the point is to avoid* that.