From: Alf P. Steinbach on
* James Kanze:
> Lucian Radu Teodorescu wrote:
>> Salt_Peter wrote:
>>>> Is the following code valid?
>
>>>> int i = 5;
>>>> void* pv = &i;
>>>> void& rv = *pv; // Error here on VC 2005
>
>>>> If not, why isn't it valid?
>
>>> Its not valid for the same reasons that the following is invalid:
>>> void v = 5;
>>> That is to say: a reference is an object and a valid object.
>>> The same can't be said of a pointer, or any pointer.
>
>> Let's make the following assumption: every type is implicitly derived
>> from void. Many C++ programmers can accept that.
>
> Name one. It's manifestly false; it is, in fact, illegal to
> derive from void (or from any incomplete type).

Note that Lucian (as I read that article, especially in light of the
rest of it) was describing a future extension, not the current language.

When discussing a future extension of the language it's hardly an
argument against that extension that it doesn't yet exist. ;-)

However, since 'void' has at least two different meanings (sometimes it
behaves like a type, sometimes like a syntactic placeholder) it's IMO a
poor choice for an 'any' type.


> Void, as a type, is an incomplete type, which can never be
> completed. And in no case can you derive from an incomplete
> type. The rules concerning convertion of T* to void* do NOT
> obey the rules of derived to base (which only works if the types
> are complete), and of course, work even in cases where
> inheritance would be illegal, e.g. int* to void*.

Let's think about what the extension would be used for.

There's not much of a technical problem, for

void& rv = *pv;

would simply be translated, internally, to

typeof(pv)& rv = pv;

(except with C++0x mumbo-jumbo-name for typeof) and

void const& r = SomeExpression();

would be translated, internally, to

typeof(SomeExpression) const& r = SomeExpression;

but in both cases with a restriction on what you could do with the
reference, namely the restriction implied by 'void'.

But what's that restriction good for?

Not very much, I think.

And then why not use the keyword 'auto' instead, to get the compiler's
deduced type instead of the restrictive 'void'?

Huh, nice idea, but where can I have seen that before?

Aha! <url: http://std.dkuug.dk/JTC1/SC22/WG21/docs/papers/2003/n1478.pdf>.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Frederick Gotham on
Joshua Lehrer posted:

> No, what I'm looking for is the ability to bind a temporary to a const
> reference to void


There's a such thing as:

(1) a reference to const
(2) a reference to non-const

, but there's no such thing as a const reference.

int &const i = whatever; /* Compiler ERROR */


> and take advantage of the C++ rules that temporaries
> will remain alive as long as the const reference bound to it.


If you bind a "reference to const" to an R-value, then the following two
are equivalent:

int const &i = 5;

and:

int const __lit = 5;

int const &i = __lit;

(i.e. the temporary object has the same scope as the reference.)


> Tell me, why is it that all pointers can degrade to void pointers, but
> all references can't degrade to void references?


All pointer types can implicitly convert to void* (apart from function
pointers, and member function pointers).

There's no such thing as a "reference to void" because there's no such
thing as an object whose type is "void", and therefore a reference cannot
be bound to such a hypothetical object. Consider:

void i;

void &j = i;


> And don't give me
> "because void is not a complete type" because I can demonstrate logical
> behavior:
>
> const void & v = Lock(mx);


Is that hypothetical code. . . or are you using a K++ compiler?

--

Frederick Gotham

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Seungbeom Kim on
James Kanze wrote:
> Lucian Radu Teodorescu wrote:
>> Let's make the following assumption: every type is implicitly derived
>> from void. Many C++ programmers can accept that.
>
> Name one. It's manifestly false; it is, in fact, illegal to
> derive from void (or from any incomplete type).
>
> Void, as a type, is an incomplete type, which can never be
> completed. And in no case can you derive from an incomplete
> type. The rules concerning convertion of T* to void* do NOT
> obey the rules of derived to base (which only works if the types
> are complete), and of course, work even in cases where
> inheritance would be illegal, e.g. int* to void*.

What you said is true, but no one argued that every type is formally
derived from void; Lucian just made a suggestion. Suggestion, by nature,
supposes something that's not true right now.

And while it's true that no type can be derived from void, we can
probably say that every type is a subtype of void, because an object
of any type can be used in any context where an object of type void
is expected, which is none; there's nothing you can do with void, so
every type is capable of everything that type void is capable of.

Conversion from derived[*|&] to base[*|&] is just a particular case
of conversion from a subtype to a supertype, and conversion from any
type[*|&] to void[*|&] can be another case, even though it's not a
conversion from derived[*|&] to base[*|&]. You could more generally
argue that any complete type is a subtype of any incomplete type, and
that any complete type should be convertible to any incomplete type.

--
Seungbeom Kim

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Seungbeom Kim on
James Kanze wrote:
> Joshua Lehrer wrote:
>> This has been a pet peeve of mine for a while, probably pretty high up
>> on my C++ wish list.
>
>> (ignoring cv-qualifications for simplicity)
>
>> If T* can degrade to void*, why can't T& degrade to void&?
>
> Because void is an incomplete type.
>
>> The following is legal, and the basis of how ScopeGuard works:
>
>> const Base & b = make_sub_class(params);
>
>> The unnamed temporary is bound to the const-reference and is guaranteed
>> to be alive for the lifetime of 'b'.
>
> It also only works if Base is a complete type.

Allowing reference to void doesn't allow creating an object of type
void; it just allows to refer to an existing object through a supertype.
Reference to Base is allowed even if Base is an abstract base class and
no complete object of Base can exist; in what regard does reference to
void differ? What loopholes do you think could it open?

And we are familiar with the analogy between pointers and references.
There are cases where one cannot replace the other, but I would hope
those cases are kept minimal, and in the case suggested above it's
obvious that you cannot substitute a pointer for a reference.

>> I sometimes find it a pain to make my implementations inherit from a
>> common base just so that I can bind a const-reference to the temporary,
>> as above. Why can't I write:
>
>> const void & v = make_sub_class(params);
>
>> or
>
>> const void & v = std::pair<Lock,Lock>(mx1,mx2);
>
>> In my mind, it makes sense. All types should be considered to inherit
>> (virtually) from void.
>
> What you're looking for isn't void, it's Object. In Java.

Sort of. I'm not sure if you can create an object of type Object in
Java, but the proposal doesn't ask to allow creating an object of type
void in C++, anyway.

> Personally, I've never missed it in C++.

Yes, what you've never missed can be what's a real pain in someone
else's neck. :-) Disagreement to the proposal would be more convincing
with an argument of possible loopholes in the type system, or breaking
existing codes [which I don't expect].

--
Seungbeom Kim

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Lucian Radu Teodorescu on
Alf P. Steinbach wrote:
> >> Let's make the following assumption: every type is implicitly derived
> >> from void. Many C++ programmers can accept that.
> >
> > Name one. It's manifestly false; it is, in fact, illegal to
> > derive from void (or from any incomplete type).
>
> Note that Lucian (as I read that article, especially in light of the
> rest of it) was describing a future extension, not the current language.

Thank you ... Indeed, I was talking about somthing which is not
implemented in C++.

>
> When discussing a future extension of the language it's hardly an
> argument against that extension that it doesn't yet exist. ;-)
>
> However, since 'void' has at least two different meanings (sometimes it
> behaves like a type, sometimes like a syntactic placeholder) it's IMO a
> poor choice for an 'any' type.

IMHO it's worse to have all kind of exceptions in the language, than to
have one good rule that works in (almost) all cases. In this case, as
you noticed currently "void" isn't really a type, and isn't really a
syntactic placeholder. And the bad thing about this duality is the fact
that we don't know the exact border of this: sometimes void behaves
like a type and we can have pointers to void, and sometimes void
doesn't behave like a type and doesn't allow us to have references of
type void.

Here is an example:
<code>

template <typename T>
struct Test
{
typedef T original_type;
typedef T* pointer_type;
typedef T& reference_type;
};

class A {};

bool b1 = boost::is_same<int, void>::value;
bool b2 = boost::is_same<int, Test<void>::original_type>::value; // (2)
Error here?
bool b3 = boost::is_same<int, Test<A>::original_type>::value;

</code>

Is there something wrong with the definition of the Test class
template? Am I doing something wrong when I try to instantiate
Test<void>, when I need the original type? Why should the creator of
the template have to think of the "void exception" when he is building
his class?

>
>
> > Void, as a type, is an incomplete type, which can never be
> > completed. And in no case can you derive from an incomplete
> > type. The rules concerning convertion of T* to void* do NOT
> > obey the rules of derived to base (which only works if the types
> > are complete), and of course, work even in cases where
> > inheritance would be illegal, e.g. int* to void*.
>
> Let's think about what the extension would be used for.
>
> There's not much of a technical problem, for
>
> void& rv = *pv;
>
> would simply be translated, internally, to
>
> typeof(pv)& rv = pv;
>
> (except with C++0x mumbo-jumbo-name for typeof) and
>
> void const& r = SomeExpression();
>
> would be translated, internally, to
>
> typeof(SomeExpression) const& r = SomeExpression;
>
> but in both cases with a restriction on what you could do with the
> reference, namely the restriction implied by 'void'.
>
> But what's that restriction good for?
>
> Not very much, I think.
>
> And then why not use the keyword 'auto' instead, to get the compiler's
> deduced type instead of the restrictive 'void'?

Indeed, this reference to void ideea doesn't help too much. Again,
let's take a piece of code:
<code>

void f1()
{
auto& obj = f();

// A lot of code folllows...
}

void f2()
{
void& obj = f();

// A lot of code folllows...
}

</code>

If you take the first look in f1() you don't know what happens to the
result of the function call. You may rush to say that obj will be
accessed in the code that follows. But this is not necessarly the
intent. One can only want to extend the scope of the object returned by
function call. IMHO, the second approach is better for this purpose as
the reader is shure that no one will access or change the state of obj
(well... almost).

Best regards,
Lucian Radu Teodorescu


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]