5 ms·
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 variabl
by proaralyst 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.
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...)
- CuriousSkeptic 2y agoNot that familiar with c++ but used to have this thought about both Java and C#. Think I’ve changed my stance on it now though. If following something like CQS the bifurcation can be thought of allowing “pure” functions and excluding code with a temporal / side-effecting component from higher order code. Not saying bifurcating on void is the best approach to handle that, but in languages where side effects are a thing something is needed to make sure higher order code and side effecting code mix properly.
- 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.