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
> 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.
Which 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.
Not 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.
And this doesn’t come anywhere near to properly making that distinction anyway: a non-void function can have all the side effects, and a void function can have no side-effects.
It also does not “make sure higher order code and side effecting code mix properly”, it just makes a subset of likely side-effecting code not mix with higher order code at all.
> 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???)).
}
I'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.
It'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.
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