4 ms·
You are equivocating on the word "void". Your statement that "a variable of type void can't be occupied" is true in functional languages where "void/Void" is of
by cvoss 2y ago
You are equivocating on the word "void". Your statement that "a variable of type void can't be occupied" is true in functional languages where "void/Void" is often used as the name of a type that isn't inhabited (assuming the language is sound/normalizing/whatever).
But here we are talking about C++, where "void" is a pseudotype that is absolutely inhabited, in some conceptual sense. Any function that is declared to return void and which returns is returning a thing that conceptually inhabits void. In this sense, std::monostate indeed captures the same concept as void, but in a much better way, because it's properly a type, not a pseudotype.
Note: Java does the same thing, effectively, with "Void" which is inhabited by exactly one value: null.
- Koshkin 2y agoIncidentally, the classic C did not have 'void'; instead, it was assumed that any function would, by default, return 'int' in the form of some value stored in the accumulator, and so the "value" of 'void' would be effectively represented by random garbage. The 'void' that was introduced explicitly in a later version of C weakened the original meaning of the unknown value by allowing pointers to 'void' and thus not requiring that the value pointed to must be always thought of as meaningless (since you could cast a pointer to void to a pointer to something else).
- proaralyst 2y agoI think it's not correct to say that void is a monotype in C++, because the compiler won't allow you to assign the result of a function marked void to a variable, and you cannot declare a variable of type void. I'd accept that it's not the same as the empty type though, given that void* can be occupied and functions marked void can return. Probably someone with more type theory than me can name this properly
- masklinn 2y ago> Probably someone with more type theory than me can name this properly Probably “garbage”. C’s void is not a type and does not behave consistently, it’s a keyword associated with arbitrary convenient behaviours for that case.
- mFixman 2y ago> I think it's not correct to say that void is a monotype in C++, because the compiler won't allow you to assign the result of a function marked void to a variable, and you cannot declare a variable of type void. The compiler does not allow you to do that particular operation out of an arbitrary restriction, but that does not make `void` a true void type. It still holds a monotype value! int bar() { std::cout << "Bar" << std::endl; return 0; } void baz() { std::cout << "Baz" << std::endl; } template <typename T> T foo(T (*f)()) { std::cout << "Foo" << std::endl; return f(); } template <typename T> T varfoo(T (*f)()) { std::cout << "Varfoo" << std::endl; T a = f(); return a; } int main() { foo(bar); // Valid (returning an int). foo(baz); // Valid (returning a void). varfoo(bar); // Valid (assigning an int). // varfoo(baz); // Invalid (assigning a void (why???)). }
- saurik 2y agoWhich is really annoying, and makes a ton of templated code in C++ have have to bifurcate on void unnecessarily. They already let me do return f(); in a void function if f also returns void... they should let me declare a variable of type void and the language is going to become a lot more pleasant.
- Y_Y 2y agoWhat are you going to put in that variable? void f(); void v = f(); void g(a){return a;} v = g(v); Maybe my imagination is failing me, but I can't see how this can do much good without at least polymorphic functions.
- masklinn 2y agoThe void value. E.g. fn f() {} let mut v: () = f(); fn g(a: ()) { a } V = g(v); > Maybe my imagination is failing me, but I can't see how this can do much good without at least polymorphic functions. Sure, it doesn’t do much useful to C save make void ever so slightly less wonky.
- gpderetta 2y agotemplate<range R, regular X, invocable<range_value<R>, X> F> requires same_as<invoke_result_t<F, R, X>, X> auto fold(R&& range, F f, X accumulator) { for(auto x: range) accumulator = f(x, accumulator); return accumulator; } I can call that with a function returning a custom unit type: enum class void_t { Void }; fold(my_range, [](auto&& elem, void_t) { return Void; }, Void); But not with void: fold(my_range, [](auto&& elem, void) { return; }, void{}); which is very annoying and requires fold to special case 'void' via metaprogramming.
- remexre 2y agoTemplates already provide that useful polymorphism; template<typename T> T callWithState(auto f) { auto old = globalState; globalState = whatever(); T out = f(); globalState = old; return out; } (forgive any syntax errors, my C++ is very rusty...)
- ackfoobar 2y agoI'm not that familiar with C, or C++. My impression is that void is a special case that doesn't need to be special, some accidental complexity that came from mapping machine instructions to a higher level language.
- rerdavies 2y agoIt's kind of baked into C grammar. And there's absolutely no compelling use-case to fix it in C. In C++, there's a very compelling case for making void an actual type, because you can't use void as a templated type, which means that templates involving functions that potentially have void return types require unpleasant amounts of template metaprogramming. Now that C++ standards committees are considering basic usability fixes (e.g. the long overdue ability to do`namespace com::microsoft::directx { }`) there's a vague possibility that somebody might look into actually fixing this some time before 2040.
- a_t48 2y agoThat namespace thing has been in since C++20, right?
- zorgmonkey 2y agoPretty sure the namespace thing was in C++17
- a_t48 2y agoAh yeah, I read the page too fast.
- rerdavies 2y agoRight. Only took 37 years to fix a usability issue that Stroustrup fully expected to be fixed at the first available opportunity. C++17 and C++20 both took up usability fixes. std::string::ends_with would be a a C++20 example. Hopefully C++23 will be similarly open to usability fixes.