'Is any type convertible to void? [duplicate]

All of the following expressions compile fine:

void();
void(5);
void("hello");
void(std::string("world"));
void(std::vector<int>{1, 2, 3});

Does this mean that any type can be converted to void? That is void is constructible from an argument of any type.

However the following function doesn't compile:

void func()
{
    return std::vector<int>{1, 2, 3};
}

But if I convert the return value to void explicitly, it compiles:

void func()
{
    return void(std::vector<int>{1, 2, 3});
}

Does it mean that all void constructors are explicit?


The answer

Yes, a value of any type can be explicitly converted to void.

Section 3.9.1/9, N3797:

The void type has an empty set of values. The void type is an incomplete type that cannot be completed. It is used as the return type for functions that do not return a value. Any expression can be EXPLICITLY converted to type cv void (5.4). An expression of type void shall be used only as an expression statement (6.2), as an operand of a comma expression (5.18), as a second or third operand of ?: (5.16), as the operand of typeid, noexcept, or decltype, as the expression in a return statement (6.6.3) for a function with the return type void, or as the operand of an explicit conversion to type cv void.



Solution 1:[1]

As said in the comment, "One way to think about void( ... ) is compute the ... including all side-effects and then throw the result away"

The same can be seen using a contrived example:

struct C 
{
    C(int) 
    {
        std::cout<<"converting constructor called"<<std::endl;
    }
};
int main()
{
    void(C(5)); //prints converting constructor called
    
}

The ones you provided are explicit type conversions and can be understood using explicit cast which states:

new-type ( )  (4)     

If new-type names a non-array complete object type, this expression is an prvalue of type new-type, designating a temporary (until C++17)whose result object is (possibly with added cv-qualifiers) (since C++17) of that type. If new-type is an object type, the object is value-initialized. If new-type is (possibly cv-qualified) void, the expression is a void prvalue without a result object (since C++17).

(emphasis mine)

The above is for the first case in your example void().


The rest of them are functional cast expression which are exactly equivalent to the corresponding C-style cast expression.

new-type ( expression )   (2)     

The functional cast expression consists of a simple type specifier or a typedef specifier (in other words, a single-word type name: unsigned int(expression) or int*(expression) are not valid), followed by a single expression in parentheses. This cast expression is exactly equivalent to the corresponding C-style cast expression.


The standard also states:

Any expression can be explicitly converted to type cv void, in which case it becomes a discarded-value expression.

An expression of type cv void shall be used only as an expression statement (9.2), as an operand of a comma expression (8.19), as a second or third operand of ?: (8.16), as the operand of typeid, noexcept, or decltype, as the expression in a return statement (9.6.3) for a function with the return type cv void, or as the operand of an explicit conversion to type cv void.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1