Topic: void


Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Mon, 10 Dec 2001 20:38:17 GMT
Raw View
"Christopher Eltschka" <celtschk@web.de> wrote in message
news:9ur0dc$cll$1@news.tuwien.ac.at...
> "Anthony Williams" <anthwil@nortelnetworks.com> writes:
>
> > "Christopher Eltschka" <celtschk@web.de> wrote in message
> > news:9t0tgd$sag$3@news.tuwien.ac.at...
>
> [...]
>
> > >
> > > You also could take the address (to get a void pointer), or you could
> > > do a reinterpret-cast to any other reference type. In effect, a void
> > > reference would be the analog of Turbo Pascals untyped variable
> > > parameters.
> >
> > I'm not sure about this. In the case below, if "incomplete" has a
> > user-defined operator&, then the code exhibits undefined behaviour,
without
> > a diagnostic.
>
> But void surely does not have an user-defined operator&, simply
> because you cannot define it.

... because void is a built-in type. True, but void is an _incomplete_ type,
and only classes, structs, unions and enums can be incomplete, all of which
can have user-defined operator&. Therefore, you could (in principle) write:

void* operator&(void& t){}

since the complete type void must be a class, struct, union or enum.

However, this is taking things too far --- I don't seriously think the user
should be permitted to write operator& for void.

> > Allowing making a const void* from a const void& implies there
> > is an actual "void" object somewhere --- you cannot safely use operator&
> > with any incomplete type, so why allow it for void?
>
> Consistency: Because it is allowed for incomplete types, if the
> complete type does not have an explicit operator&
>
> And it's not completely right that you cannot safely use operator&
> with _any_ incomplete type. You can f.ex. use it safely on all
> incomplete types you got from a C interface. And I think defining
> operator& makes a type a non-POD, therefore if the type is documented
> as POD you'd be safe, too.

My thought was simply that we should give void the _minimum_ set of
operations that can safely be done on an incomplete type T, if we know
nothing about it. Since _in principle_ a type could have a user-defined
operator&, which would yield undefined behaviour for incomplete types, I
think that applying operator& to a void reference should be illegal. This
also means that the compiler then does not have to actually generate a
(fake) void object for

void f();
const void& g(const void&);
g(f());

to distinguish it from

const char *p="hello";
void * q=static_cast<void*>(p);
g(*q);

as dereferencing a void pointer essentially is a no-op --- the resulting
reference cannot be used for anything except passing to void-reference
accepting functions. A void reference is therefore just a placeholder,
occupying no space, and with no valid operations. Anything used to
initialize a void reference is just discarded.

> > > I'm not sure if there should be another exception for void value
> > > parameters, though. It's unfortunate enough that we have this strange
> > > "f(void)" thing. Further extending on this is IMHO not a good idea.
> >
> > I am not sure what you mean here.
>
> Functions taking void, which I had the impression you wanted. But
> since you made clear that you only wanted function taking _references_
> to void, my concerns about it are void anyway (however, I think the
> rules of the English language allow references to it anyway :-)).

:-)

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optical Components Ltd
The opinions expressed in this message are not necessarily those of my
employer



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Christopher Eltschka <celtschk@web.de>
Date: Fri, 7 Dec 2001 18:09:12 GMT
Raw View
"Anthony Williams" <anthwil@nortelnetworks.com> writes:

> "Christopher Eltschka" <celtschk@web.de> wrote in message
> news:9t0tgd$sag$3@news.tuwien.ac.at...

[...]

> >
> > You also could take the address (to get a void pointer), or you could
> > do a reinterpret-cast to any other reference type. In effect, a void
> > reference would be the analog of Turbo Pascals untyped variable
> > parameters.
>
> I'm not sure about this. In the case below, if "incomplete" has a
> user-defined operator&, then the code exhibits undefined behaviour, without
> a diagnostic.

But void surely does not have an user-defined operator&, simply
because you cannot define it.

> Allowing making a const void* from a const void& implies there
> is an actual "void" object somewhere --- you cannot safely use operator&
> with any incomplete type, so why allow it for void?

Consistency: Because it is allowed for incomplete types, if the
complete type does not have an explicit operator&

And it's not completely right that you cannot safely use operator&
with _any_ incomplete type. You can f.ex. use it safely on all
incomplete types you got from a C interface. And I think defining
operator& makes a type a non-POD, therefore if the type is documented
as POD you'd be safe, too.

>
> struct incomplete;
> incomplete* p;
> incomplete& ref=*p;
> incomplete* p2=&ref; // undefined behaviour if user-defined operator&

But defined behaviour if no user-defined operator&.

[...]

> > > Any comments?
> >
> > I'm not sure how useful it would be, but allowing void references
> > would definitively make the type system a bit more consistent.
>
> That was the idea. I can think of several uses in generic programming.
>
> > I'm not sure if there should be another exception for void value
> > parameters, though. It's unfortunate enough that we have this strange
> > "f(void)" thing. Further extending on this is IMHO not a good idea.
>
> I am not sure what you mean here.

Functions taking void, which I had the impression you wanted. But
since you made clear that you only wanted function taking _references_
to void, my concerns about it are void anyway (however, I think the
rules of the English language allow references to it anyway :-)).

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Balog Pal" <pasa@lib.hu>
Date: Sat, 17 Nov 2001 23:28:57 GMT
Raw View
"Anthony Williams" <anthwil@nortelnetworks.com> wrote in message

> It occurs to me that "void" is a most peculiar construct. In some cases it
> is an incomplete type, just like any other, so we can create a pointer to
> void, or a typedef name for it,

It's just confusion in words. Actually you can never have a poitner to void.
void * in  C++ is just a common 'keyword overload' case like static, but the meaning is completely different, and unrelated to type void.

There was a long discussion on that topic on clcm, just I can't recall the subject.

Paul

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Mon, 19 Nov 2001 16:54:26 GMT
Raw View
"Christopher Eltschka" <celtschk@web.de> wrote in message
news:9t0tgd$sag$3@news.tuwien.ac.at...
> "Anthony Williams" <anthwil@nortelnetworks.com> writes:
> > However, you cannot have a reference-to-void,
>
> More exactly, you cannot have an lvalue of void type. For example,
> dereferencing a pointer to void is not possible.

True.

> > and you cannot use a void
> > expression as a function parameter.
>
> Yes. And since "f(void)" has a special meaning due to C
> compatibility, it would be hard to change this.
>
> > Thus, you cannot say
> >
> > void func3(const void&){}
>
> This is not a funciton taking void, but a function taking void
> const&. The fact that this is not possible is a direct consequence to
> the fact that void lvalues are not allowed.
>
> > // or
> > template<typename T>
> > void func4(const T&){return 0;}
> > func4(func1());
>
> Same here.

> >
> > "void" is also the only incomplete type that can be used as a complete
type
> > (!) --- expressions can freely be converted to type "void", and
functions
> > can return void.
>
> The first one I don't know why it was introduced; the second one was
> explicitly introduced to simplify templates.

conversion to "void" (using static_cast) is to allow explicit discarding of
return values.
functions can return void to simplify templates _by making the type system
more consistent_

> >
> > Finally, void can also be used to indicate "no parameters" in a function
> > definition
> >
> > void f(void){}
>
> Yes, this is the C compatibility thing I mentioned above. BTW, even in
> C, this notation is due to backwards compatibility, because the empty
> parameter list means something quite different in C.

True.

> >
> > Though this cannot be used in a template --- the declaration of func()
> > generates an error for MyStruct<void>:
>
> Yes, because this "void" is an artefact - in "f(void)" f does not take
> an argument of type void; it doesn't take any argument at all.

Yes. Yuck.

> > It strikes me that it would be useful if "void" could act as a proper
> > incomplete type, in addition to the special cases, void expressions
could be
> > passed to functions expecting "const void&" parameters, and that this
would
> > work with function template argument type deduction. You wouldn't be
able to
> > do anything with a void reference, except ignore it, or pass it to
another
> > function accepting a void reference, but it would, IMO, make the type
system
> > a fraction more consistent, which would be useful for generic
programming.
>
> You also could take the address (to get a void pointer), or you could
> do a reinterpret-cast to any other reference type. In effect, a void
> reference would be the analog of Turbo Pascals untyped variable
> parameters.

I'm not sure about this. In the case below, if "incomplete" has a
user-defined operator&, then the code exhibits undefined behaviour, without
a diagnostic. Allowing making a const void* from a const void& implies there
is an actual "void" object somewhere --- you cannot safely use operator&
with any incomplete type, so why allow it for void?

struct incomplete;
incomplete* p;
incomplete& ref=*p;
incomplete* p2=&ref; // undefined behaviour if user-defined operator&

My thought was really to just allow (const) references to void. Therefore a
void-returning function could be used as a parameter for a function
accepting a const void& parameter, which would allow template type deduction
for void return types. Therefore the following (and only minor variations on
the following) should be allowed:

int f1(){return 0;}
void f2() {}
void f3() { return f2(); }

void f4(const void&v){ return v;}
const void& f5(const void& v) { return v;}

template<typename T>
T f6(const T& t){ return t;}

f4(f2());
f4(f3());
f5(f2());
f6(f1());
f6(f2());

> > Any comments?
>
> I'm not sure how useful it would be, but allowing void references
> would definitively make the type system a bit more consistent.

That was the idea. I can think of several uses in generic programming.

> I'm not sure if there should be another exception for void value
> parameters, though. It's unfortunate enough that we have this strange
> "f(void)" thing. Further extending on this is IMHO not a good idea.

I am not sure what you mean here.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optical Components Ltd
The opinions expressed in this message are not necessarily those of my
employer



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Wed, 14 Nov 2001 23:20:18 GMT
Raw View
It occurs to me that "void" is a most peculiar construct. In some cases it
is an incomplete type, just like any other, so we can create a pointer to
void, or a typedef name for it, or even use it as a template type parameter.
You can even use expressions of void type in a return statement, provided
the function which contains the return statement has void type.

typedef void MyVoid;
void* p;
void func1(){}
MyVoid func2()
{
    return func1();
}
template<typename T>
struct MyStruct
{
    typedef T Type;
};

MyStruct<void> msVoid;

However, you cannot have a reference-to-void, and you cannot use a void
expression as a function parameter. Thus, you cannot say

void func3(const void&){}
// or
template<typename T>
void func4(const T&){return 0;}
func4(func1());

"void" is also the only incomplete type that can be used as a complete type
(!) --- expressions can freely be converted to type "void", and functions
can return void.

Finally, void can also be used to indicate "no parameters" in a function
definition

void f(void){}

Though this cannot be used in a template --- the declaration of func()
generates an error for MyStruct<void>:

template<typename T>
struct MyStruct
{
    void func(T){}
};

MyStruct<void> ms;
ms.func();

It strikes me that it would be useful if "void" could act as a proper
incomplete type, in addition to the special cases, void expressions could be
passed to functions expecting "const void&" parameters, and that this would
work with function template argument type deduction. You wouldn't be able to
do anything with a void reference, except ignore it, or pass it to another
function accepting a void reference, but it would, IMO, make the type system
a fraction more consistent, which would be useful for generic programming.

Any comments?

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optical Components Ltd
The opinions expressed in this message are not necessarily those of my
employer


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Christopher Eltschka <celtschk@web.de>
Date: Thu, 15 Nov 2001 17:22:37 GMT
Raw View
"Anthony Williams" <anthwil@nortelnetworks.com> writes:

> It occurs to me that "void" is a most peculiar construct. In some cases it
> is an incomplete type, just like any other, so we can create a pointer to
> void, or a typedef name for it, or even use it as a template type parameter.
> You can even use expressions of void type in a return statement, provided
> the function which contains the return statement has void type.

Yes.

[...]

> However, you cannot have a reference-to-void,

More exactly, you cannot have an lvalue of void type. For example,
dereferencing a pointer to void is not possible.

> and you cannot use a void
> expression as a function parameter.

Yes. And since "f(void)" has a special meaning due to C
compatibility, it would be hard to change this.

> Thus, you cannot say
>
> void func3(const void&){}

This is not a funciton taking void, but a function taking void
const&. The fact that this is not possible is a direct consequence to
the fact that void lvalues are not allowed.

> // or
> template<typename T>
> void func4(const T&){return 0;}
> func4(func1());

Same here.

>
> "void" is also the only incomplete type that can be used as a complete type
> (!) --- expressions can freely be converted to type "void", and functions
> can return void.

The first one I don't know why it was introduced; the second one was
explicitly introduced to simplify templates.

>
> Finally, void can also be used to indicate "no parameters" in a function
> definition
>
> void f(void){}

Yes, this is the C compatibility thing I mentioned above. BTW, even in
C, this notation is due to backwards compatibility, because the empty
parameter list means something quite different in C.

>
> Though this cannot be used in a template --- the declaration of func()
> generates an error for MyStruct<void>:

Yes, because this "void" is an artefact - in "f(void)" f does not take
an argument of type void; it doesn't take any argument at all.

[...]

> It strikes me that it would be useful if "void" could act as a proper
> incomplete type, in addition to the special cases, void expressions could be
> passed to functions expecting "const void&" parameters, and that this would
> work with function template argument type deduction. You wouldn't be able to
> do anything with a void reference, except ignore it, or pass it to another
> function accepting a void reference, but it would, IMO, make the type system
> a fraction more consistent, which would be useful for generic programming.

You also could take the address (to get a void pointer), or you could
do a reinterpret-cast to any other reference type. In effect, a void
reference would be the analog of Turbo Pascals untyped variable
parameters.

> Any comments?

I'm not sure how useful it would be, but allowing void references
would definitively make the type system a bit more consistent.

I'm not sure if there should be another exception for void value
parameters, though. It's unfortunate enough that we have this strange
"f(void)" thing. Further extending on this is IMHO not a good idea.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]