What is const void, and is it a valid return type?
Asked Answered
M

4

99

The description of std::is_void states that:

Provides the member constant value that is equal to true, if T is the type void, const void, volatile void, or const volatile void.

Then what could be const void, or a volatile void ?

This answer states that const void return type would be invalid (however compiles on VC++ 2015)

const void foo() { }

If by standard, const void is invalid (VC being wrong) - then what is const void?

Metameric answered 17/6, 2016 at 12:9 Comment(5)
The answer you link to doesn't state that it would be invalid, it states that it would be "meaningless", which I would take to mean "doesn't offer any benefits over void without const".Intrusive
@hvd, the answer states that compiler should warn/error about such qualification. By that I presume C++ standard doesn't allow qualifications with voidMetameric
The answer states that the compiler should warn about such qualification, it doesn't mention an error, and an error would be wrong. That remark is just about quality of implementation, not about conformance, but I can understand that that's not at all clear from the remark itself.Intrusive
@Metameric the standard doesn't specify that there should be a warning when you use meaningless code. It was a decision by gcc to give you an additional hint that this code doesn't do anything. But VC isn't wrong in any way.Contaminate
@Metameric The answer states that clang gives a warning, and that, in the author's opinion, other compilers should. If the standard didn't allow it, it would be an error, not a warning.Fang
D
102

const void is a type which you can form a pointer to. It's similar to a normal void pointer, but conversions work differently. For example, a const int* cannot be implicitly converted to a void*, but it can be implicitly converted to a const void*. Likewise, if you have a const void* you cannot static_cast it to an int*, but you can static_cast it to a const int*.

const int i = 10;
void* vp = &i;                           // error
const void* cvp = &i;                    // ok
auto ip = static_cast<int*>(cvp);        // error
auto cip = static_cast<const int*>(cvp); // ok
Delagarza answered 17/6, 2016 at 12:16 Comment(4)
While your answer is good, it doesn't state the reason of const void, but its all around void and non-void pointers [ with (non-)const-ness ].Metameric
@Ajay: I disagree. A const void* is the only reason you would ever see const void. It might be passed around as a template argument, but that argument type will only ever be instantiated with a * at the end of it.Delagarza
@BenjaminLindley You may also see const void in question asked by language lawyerSubak
@Ajay: At some point this question becomes a philosophy question. The "reason" of const void is that all types in C++ can be made const. It "exists" in the same way that void exists. @Benjamin Lindley's answer explains what it is by way of when you see it and how you use it.Rendarender
C
25

As void, const void is a void type. However, if const void is a return type, the const is meaningless (albeit legal!), because [expr]/6:

If a prvalue initially has the type “cv T”, where T is a cv-unqualified non-class, non-array type, the type of the expression is adjusted to T prior to any further analysis.

However, it is a valid type itself and occurs in e.g. C-standard library functions, where it's used to ensure const-correctness of argument pointers: int const* cannot be converted to void*, but void const*.

Covey answered 17/6, 2016 at 12:22 Comment(5)
const void as a return type does affect the function type, so it's not completely meaningless.Subak
@Subak Except it is in every practical sense, because neither the signature of the function nor the type of a call to it are affected.Covey
Well it can change the signature of a function template. +1 nonethelessSubak
@Subak Fair enough - it still is a waste of keystrokes, though.Covey
We normally see: const int * cannot go to void *, but const void *.Corrinacorrine
N
21

Types can be the result of templates; a template might state const T, and be instantiated with T as void.

The linked answer is misled, or rather, limited in view in that it regards the special case of a non-template type, and even then const void might be meaningless, but it is valid code.

Names answered 17/6, 2016 at 12:16 Comment(0)
F
0

I have come across a need to use const void in the implementation of a lookup table. My intention was to create a list of constant pointers to routines.

When creating the routines, I need to have a const void return in order to prevent the compiler from complaining.

const void lookup_1(void* v)
{
    printf("This is lookup 1\r\n");
}

const void lookup_2(void* v)
{
    printf("This is lookup 2\r\n");
}


const void(*lookup_table[])(void*) =
{
    lookup_1,
    lookup_2
}

It doesn't look particularly aesthetic but I haven't found a more elegant way of doing what I intend. So to sum-up I would say it's perfectly reasonable to use in this context and maybe others that I haven't considereda.

Forwarder answered 23/3 at 11:11 Comment(3)
Welcome to SO! Clang gives the following warning for your code when compiled with -Wextra: warning: 'const' type qualifier on return type has no effect [-Wignored-qualifiers]. Removing all three consts solves the problem. P.S. you almost always don't need to include \r in printf since it does the conversion of newline characters automatically for you in text mode.Asia
This is not the point. I want the entries in the lookup table to be const. I haven't found a better way of achieving what I want. If I remove all the const statements, the entries in the lookup table will no longer be constant.Forwarder
I see that you were trying to do. Unfortunately, your code doesn't make lookup_table constant: godbolt.org/z/Y8edEfKoK ; it's still possible to change it and e.g. assign lookup_table[0] to lookup_2. Instead, you need to put const after *, i.e. void (*const lookup_table[])(void*) = {lookup_1, lookup_2} or (better) use using or typedef for the function pointer and only then use const: godbolt.org/z/Gr71dfdeqAsia

© 2022 - 2024 — McMap. All rights reserved.