views:

254

answers:

10

I was wondering, why can't there be a void data type that is not a pointer?

Surely you could get past the whole determined size thing by having

void4
void8
void32

And then only being allowed to 'cast' a void data type to another class if its size is equal or under to the classes size.

Is there something that I'm missing, or does the C++ committee just consider it bad practise?

EDIT:

I haven't explained myself very well, so I'll give an example of its use:

 main()
{
    /* 

     Lets make a list of unknown elements

     std::string is 8 bytes, and float is 4
     bytes, so we'll reserve 8 byte sequences

     */

    vector<void8> elements;

    elements.push_back((void8) string("First string element"));

    elements.push_back((void8) float(5.76) );

    elements.push_back((void8) string("Third string element"));

    // Ect.

    cout << (string) elements[0];
    cout << (float) elements[1];
    cout << (string) elements[2];
    cout << (float) elements[2]; // Garbage


    void1 data;

    data = (void1) bool(1);
    data = (void1) unsigned int(80094); // Error, not enough size
}

Its named void because you don't know what type it is currently storing, similar to the void pointer.

+2  A: 

What would be the meaning of a "void" data type? I don't think there is a valid one, so that's probably why it doesn't exist.

Oli Charlesworth
-1. I do not think this is an answer, I think this should actually be a comment.
Default
@Michael: It's an answer in the form of a question. My implication is "this would have no meaning, so that's why it doesn't exist".
Oli Charlesworth
It would be better if it was a haiku.
SurDin
Since the OP is asking why it does not exist it might be that he would not know the answer to this question either. However, `There would be no meaning to a "void" data type, because...`, I could accept.
Default
@Michael: Fair enough; answer edited accordingly.
Oli Charlesworth
@SurDin: The void is nothing. What is the type of the void? Unask the question.
Mike Seymour
+2  A: 

What is void? It is nothing, emptyness. Void32, lol! void used to designate function that returns nothing. In other languages there is keyword 'procedure' or 'sub'. Pointer to void is pointer to unknown (second usage of void). That's two purposes void serves.

Update: I think, author wants to designate unknown type with known size. void32* is pointer to some entity with sizeof 32 bits, void8* is pointer to 8-bit entities and so on. But it's easily emulated with int32*, char* without language extension.

alxx
`void8` is too big - I want a `void7`
Tim Robinson
the real question is, can I store a `void32` into a `void4`? After all, if it just contains void, there's no reason why it shouldn't fit in a smaller data type.
jalf
A: 

Having a void datatype would unnecessarily complicate things. and Moreover what would the datatype be doing if it is called void.

I guess you are referring to a datatype that may funciton like a void one but you may want to change the name and not call it void.

ckv
+3  A: 

In a strongly typed language, all data has a type, so there is no concept of "void" as a datatype. In C and C++, it's meanings are either "no data" (as a return value), or "data whose type you don't know" (as a pointer target).

You are proposing an in-between state of "data whose type you don't know but whose size you do", presumably as an opaque version of a type you pass by value. Besides being rather a dangerous thing to do (since you have to manually update all the code using the opaque type when you change the size of the real type), this can already be done without adding weird extensions to the language, for example:

struct void8 { char bytes[8]; };

This could be used in conjunction with reinterpret_cast to pass POD types around as opaque lumps, in much the way you suggest. Using it with non-POD types is even more likely to invoke undefined behaviour than using void* to refer to non-POD types.

It would be safer and more idiomatic to handle opaque types as pointers or references to named types that have been declared but not defined, or something like boost::any if you want value semantics. There's rarely a need to use "void" as a placeholder type in C++.

Mike Seymour
I think you mean `struct void32` rather than `struct void8`?
therefromhere
@therefromhere: that depends on whether you're counting bits or bytes. The recent edit to the question implies bytes, so I'll stick to that.
Mike Seymour
This is a no-solution to an ill-formed problem. What would be the usage of such a class? Will you memcpy the contents of other objects into this structure? `reinterpret_cast`? The sample code in the question will not work out of the box, and even if you make it *work* with the appropriate casting, the semantics are still wrong. For all non-pod types you will be in undefined-behavior land.
David Rodríguez - dribeas
@David: It wasn't intended as a solution, just an indication that it could be done if it really is the best approach in a particular situation (which it almost certainly isn't), as an aside to my main answer that you should use a more idiomatic approach. You'd use it by using `reinterpret_cast` to convert between references to `void8` and POD types, and using the default copy semantics of `void8` to pass it around. As you say, it's not safe to use for non-POD.
Mike Seymour
+2  A: 

What you're looking for already exists. It is called char. An array of char can be used to store unknown objects into, because a char is basically C++'s name for a byte. So to store unknown or variable types of objects into a single array, you use an array of bytes, not an array of nothing, which void would be.

The point in a void pointer is that we don't know what it points to. We don't know the size of the object it points to either. So a void4 doesn't make much sense. It's no longer "void" if we know the object's size. The only thing we can do with an unknown object is to point to it. We can't store it anywhere because we don't know if it is a POD object, and we don't know how big it is, or its alignment requirements. So we certainly not store it into an array. All we can do is create a pointer to it, and we already have void pointers for that.

And of course, a fun little question:

What is the type T here?

void foo(void* p) {
   T q = *p;
}

void4? void32? Or just void? How big should the object be? What do we know about it? Is it a POD type?

jalf
Fair enough - the name isn't right
Tomas Cokis
+8  A: 

It's called a boost::variant or boost::any. It's the size of the maximum allowed data type + sizeof(pointer) and is totally type safe.

DeadMG
+1 This is most likely what the OP is really looking for.
Jon Purdy
I know that boost is an alternative, but I'm wondering why you can't use the method I outlined, considering it would be cheaper memorywise
Tomas Cokis
@Tomas Cokis: Because you'll invoke huge quantities of undefined behaviour memcpying around classes and such that need non-trivial construction, destruction, etc. Also, you would have to be creating hundreds of millions of objects in order to notice sizeof(pointer). Finally, it would be totally nonportable as sizeof(std::string) is undefined. Data is not just bits and bytes, it requires vast quantities of compile-time metadata to be used safely. Either you store that data at runtime (boost::variant) or you make it one specific type at compile-time, so you don't need to store it.
DeadMG
A: 

void* is not a pointer which is void, as in invalid. It's a pointer to a void, as in there's nothing there.

Type type void itself is defined by the lack of a value. There are no bits in its representation. It cannot form objects.

What you are describing can be casted to and from. Therefore it contains information. Therefore it is not an empty void.

What you are describing is simply an int where the numerical value is ignored. But the suggested uses are poor practice.

Potatoswatter
A: 

void is an "uninhabited" type, meaning there are no possible values of type void. Since there are no possible values, it takes no space to store a void. Therefore, sized void values would be meaningless.

Stepping back a moment: C and C++ fairly consistently recognize void as meaning "nothing". You can have a pointer to nothing, and use it to carry the value of a pointer to something around, but you cannot dereference it - void has no value that you can do anything with.

Note as well that the void-is-nothing carries through to the void pointer case: while some compilers such as GNU allow you to do pointer arithmetic on void* values as if they were char*, the standards prohibit pointer arithmetic on void* because, since void is nothing, it has no meaningful size.

So, I think the answer is: it would be meaningless. void is nothing, and you can't store nothing in a value.

Michael E
A: 

I'm going to assume you know a little more about the things that you will be storing than just their size, otherwise I don't believe there is much point in storing those items.

I think that you might want to take a look at unions. A union reserves enough space to hold the largest member of the union and then depending on how you reference the union, selects the "appropriate" amount of space and gives it to you as the type you request.

That said, much like casting an array of characters to whatever type you are actually looking for, you should think hard before you use this sort of feature.

BitShifter
A: 

If there were a void datatype I think it should represent nothing and just swallow anything stored into it.

you can say

(void)func1();

so why not

void x;
x = func1();

or

void func2() {
   void x;
   ...
   return x;
}

and as function arguments

int func3(int x, void y, char z);

void x = func3(1,2);
x = func3(1,x,2);

Using void in an expression is an error

I can see uses for this in some template coding.

adrianm
A void function can directly return the "result" from another void function, and yes, *that* is useful in case of templates. (That is, nothing is really returned, it is just allowed syntactically.)
UncleBens