Use of (void) before a function call [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
casting unused return values to void
What is the purpose of (void) before a function call, for example
(void)func1();
I assume this is the same as simply calling func1();
Therefore is the (void) call simply to let other programmers know that the return type will be ignored, for instance if func1() had a return type of int, or does the compiler perhaps perform some optimizations on the function? Perhaps there is another reason behind it altogether - is it even legal C++ or perhaps is it a remnant of C seen in some legacy code.
Thanks

A cast to void can have semantic effect in one case: where a value is an operand of the comma operator and overrides the comma operator, a cast to void will suppress it:
struct S {
int operator,(int) { return 0; }
};
std::cout << (S(), 42) << '\n'; // prints '0'
std::cout << ((void) S(), 42) << '\n'; // prints '42'

It prevents warning if some function are declared with attribute : "Warn if return value not used/checked"
Maybe a duplicate of Warning: ignoring return value of 'scanf', declared with attribute warn_unused_result
Check the documentation of gcc : http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html (warn_unused_result) for more details

It means very little. It is explicitly turning the line to a void expression, that is an expression that is only used for its side effects and whose value is discarded. So the lines
func1();
and
(void)func1();
will do the same thing. There could be some optimization that can be performed if the compiler knows the value of the expression is not used, but it is likely that compiler can figure it out with or without the explicit (void).
It could be used as a form of documentation where the programmer is trying to make it obvious that they are not using the value of the expression.

Another strange use is to allow the function of unknown return type to be used adjacent to the , operator as a sequence operator. Ie, decltype( f(), g() ) technique, where you want to say "f can be operated on with (), as can g, and I want this type to be the type that g() returns". However, if f() returns a type such that operator, is overloaded, the result will be unexpected.
So you do decltype( void(f()), g() ), and discard the return value of f() before invoking operator,, so you are guaranteed to get the built-in sequence operator instead of some unknown override type.

Related

What is the different between +[](){}; and (+[](){}); and why the expression is valid

As the title stated. The code is compiled using GNU c++2a
int main(){
(+[](){});
return 0;
}
Compiles fine.
However, the following code generates warning: value computed is not used [-Wunused-value]
int main(){
+[](){};
return 0;
}
Further question is: my understanding about the expression [](){} is, it returns an r-value object std::function<void()>. While, I don't know there is a unary operator +, when the + applies on any r-value, should it be a compile error generated? Or maybe because of the operator precedence, the expression is interpreted in another way?
{} is, it returns an r-value object std::function<void()>
No, it creates a lambda/closure which is its own kind of thing. There are cases when that is turned into a std::function, but what you're actually getting is much more similar to a functor (a class that implements operator()) than a std::function - which is a type-erased holder for things which can be called.
The + sign forces the closure to be turned into a function pointer (because that's the only thing thats "easy" to convert to which can have a unary + applied to it), which when wrapped in () "uses" the pointer value in a list context. Without that, you compute a function pointer but then discard it immediately. It's telling you that your + sign is silly.

Is "assert (this)" a viable pattern?

Suppose the C++ below. Before calling of a->method1() it has an
assert (a) to check if a is sane.
The call a->method2() has no such assertion; instead method2 itself
checks for a valid this by means of assert (this).
It that viable code re. the C++ specification?
Even if it's covered by the standard, it not good style of course, and
it's error prone if the code ever changes, e.g. if the method is
refactored to a virtual method. I am just curios about what the
standard has to say, and whether g++ code words by design or just by
accident.
The code below works as expected with g++, i.e. the assertion in
method2 triggers as intended, because just to call method2 no
this pointer is needed.
#include <iostream>
#include <cassert>
struct A
{
int a;
A (int a) : a(a) {}
void method1 ()
{
std::cout << a << std::endl;
}
void method2 ()
{
assert (this);
std::cout << a << std::endl;
}
};
void func1 (A *a)
{
assert (a);
a->method1();
}
void func2 (A *a)
{
a->method2();
}
int main ()
{
func1 (new A (1));
func2 (new A (2));
func2 (nullptr);
}
Output
1
2
Assertion failed: this, file main.cpp, line 16
Even if it's [permitted] by the standard
It isn't.
it not good style of course
Nope.
and it's error prone if the code ever changes, e.g. if the method is refactored to a virtual method.
I concede that a virtual member function is more likely to cause a "crash" here, but you already have undefined behaviour and that's not just a theoretical concern: you can expect things like the assertion or conditions to be elided, or other weird things to happen.
This pattern is a big no-no.
I am just curios about what the standard has to say
It says:
[expr.ref/2] [..] For the second option (arrow) the first expression shall be a prvalue having pointer type. The expression E1->E2 is converted to the equivalent form (*(E1)).E2 [..]
[expr.unary.op/1] The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. [..]
Notice that it doesn't explicitly say "the object must exist", but by saying that the expression refers to the object, it implicitly tells us that there must be an object. This sort of "gap" falls directly into the definition of undefined behaviour, by design.
whether g++ code words by design or just by accident.
The last one.
Answering your question up front: "C++: Is "assert (this)" a viable pattern?" - No.
assert(this); is pointless. The C++ standard guarantees that the this pointer is never nullptr in valid programs.
If your program has undefined behaviour then all bets are, of course, off and this might be nullptr. But an assert is not the correct fix in that case, fixing the UB is.
this cannot be nullptr, (else there is already undefined behavior).
in your case
a->method2(); // with a == nullptr
invokes undefined behavior, so checking afterward is useless.
Better signature to mean not null pointer is reference:
void func3(A& a)
{
a.method1();
}
int main ()
{
A a1(1); // no new, so no (missing) delete :-)
A a2(2);
func1(&a1);
func2(&a2);
func2(nullptr); :/
func3(a1);
}

Is it safe to take the address of a temporary?

In my program, I would like to take the address of a temporary. Here is an example:
#include <iostream>
struct Number {
int value;
Number(int n) {
value = n;
}
};
void print(Number *number) {
std::cout << number->value << std::endl;
}
int main() {
Number example(123);
print(&example);
print(&Number(456)); // Is this safe and reliable?
}
This would output:
123
456
To compile, the -fpermissive flag is requied.
Here is my question: is this safe and reliable? In what possible case could something go wrong?
If your definition of "safe and reliable" includes "will compile and produce the same results if the compiler is updated" then your example is invalid.
Your example is ill-formed in all C++ standards.
This means, even if a compiler can be coerced to accept it now, there is no guarantee that a future update of your compiler will accept it or, if the compiler does accept the code, will produce the same desired effect.
Most compiler vendors have form for supporting non-standard features in compilers, and either removing or altering support of those features in later releases of the compiler.
Consider changing your function so it accepts a const Number & rather than a pointer. A const reference CAN be implicitly bound to a temporary without needing to bludgeon the compiler into submission (e.g. with command line options). A non-const reference cannot.
&Number(456) is an error because the built-in & operator cannot be applied to an rvalue. Since it is an error, it is neither safe nor reliable. "What could go wrong" is that the code could be rejected and/or behave unexpectedly by a compiler which follows the C++ Standard. You are relying on your compiler supporting some C++-like dialect in which this code is defined.
You can output the address of the temporary object in various ways. For example add a member function auto operator&() { return this; } . The overloaded operator& can be applied to prvalues of class type.
Another way would be to have a function that is like the opposite of move:
template<typename T>
T& make_lvalue(T&& n)
{
return n;
}
and then you can do print(&make_lvalue(Number(456)));
If you are feeling evil, you could make a global template overload of operator&.
This is fine but..
Number *a;
print(a); // this would be a null ptr error
How I would change it is
void print(const Number num) // make the paramater const so it doesnt change
{
std::cout << num.value << std::endl; // note the . instead of -> cuz this is a reference not a pointer
}
You would remove the "&" from your code like:
Number example(123);
print(example);
print(Number(456));
and if you need to pass a pointer you just put a "*" to dereference it.
chasester

c or c++: specify return type when calling a function [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
casting unused return values to void
What is the purpose of (void) before a function call, for example
(void)func1();
I assume this is the same as simply calling func1();
Therefore is the (void) call simply to let other programmers know that the return type will be ignored, for instance if func1() had a return type of int, or does the compiler perhaps perform some optimizations on the function? Perhaps there is another reason behind it altogether - is it even legal C++ or perhaps is it a remnant of C seen in some legacy code.
Thanks
A cast to void can have semantic effect in one case: where a value is an operand of the comma operator and overrides the comma operator, a cast to void will suppress it:
struct S {
int operator,(int) { return 0; }
};
std::cout << (S(), 42) << '\n'; // prints '0'
std::cout << ((void) S(), 42) << '\n'; // prints '42'
It prevents warning if some function are declared with attribute : "Warn if return value not used/checked"
Maybe a duplicate of Warning: ignoring return value of 'scanf', declared with attribute warn_unused_result
Check the documentation of gcc : http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html (warn_unused_result) for more details
It means very little. It is explicitly turning the line to a void expression, that is an expression that is only used for its side effects and whose value is discarded. So the lines
func1();
and
(void)func1();
will do the same thing. There could be some optimization that can be performed if the compiler knows the value of the expression is not used, but it is likely that compiler can figure it out with or without the explicit (void).
It could be used as a form of documentation where the programmer is trying to make it obvious that they are not using the value of the expression.
Another strange use is to allow the function of unknown return type to be used adjacent to the , operator as a sequence operator. Ie, decltype( f(), g() ) technique, where you want to say "f can be operated on with (), as can g, and I want this type to be the type that g() returns". However, if f() returns a type such that operator, is overloaded, the result will be unexpected.
So you do decltype( void(f()), g() ), and discard the return value of f() before invoking operator,, so you are guaranteed to get the built-in sequence operator instead of some unknown override type.

What is the point of noreturn?

[dcl.attr.noreturn] provides the following example:
[[ noreturn ]] void f() {
throw "error";
// OK
}
but I do not understand what is the point of [[noreturn]], because the return type of the function is already void.
So, what is the point of the noreturn attribute? How is it supposed to be used?
The [[noreturn]] attribute is supposed to be used for functions that don't return to the caller. That doesn't mean void functions (which do return to the caller - they just don't return a value), but functions where the control flow will not return to the calling function after the function finishes (e.g. functions that exit the application, loop forever or throw exceptions as in your example).
This can be used by compilers to make some optimizations and generate better warnings. For example if f has the [[noreturn]] attribute, the compiler could warn you about g() being dead code when you write f(); g();. Similarly the compiler will know not to warn you about missing return statements after calls to f().
noreturn doesn't tell the compiler that the function doesn't return any value. It tells the compiler that control flow will not return to the caller. This allows the compiler to make a variety of optimizations -- it need not save and restore any volatile state around the call, it can dead-code eliminate any code that would otherwise follow the call, etc.
It means that the function will not complete. The control flow will never hit the statement after the call to f():
void g() {
f();
// unreachable:
std::cout << "No! That's impossible" << std::endl;
}
The information can be used by the compiler/optimizer in different ways. The compiler can add a warning that the code above is unreachable, and it can modify the actual code of g() in different ways for example to support continuations.
Previous answers correctly explained what noreturn is, but not why it exists. I don't think the "optimization" comments is the main purpose: Functions which do not return are rare and usually do not need to be optimized. Rather I think the main raison d'ĂȘtre of noreturn is to avoid false-positive warnings. For example, consider this code:
int f(bool b){
if (b) {
return 7;
} else {
abort();
}
}
Had abort() not been marked "noreturn", the compiler might have warned about this code having a path where f does not return an integer as expected. But because abort() is marked no return it knows the code is correct.
Type theoretically speaking, void is what is called in other languages unit or top. Its logical equivalent is True. Any value can be legitimately cast to void (every type is a subtype of void). Think about it as "universe" set; there are no operations in common to all the values in the world, so there are no valid operations on a value of type void. Put it another way, telling you that something belongs to the universe set gives you no information whatsoever - you know it already. So the following is sound:
(void)5;
(void)foo(17); // whatever foo(17) does
But the assignment below is not:
void raise();
void f(int y) {
int x = y!=0 ? 100/y : raise(); // raise() returns void, so what should x be?
cout << x << endl;
}
[[noreturn]], on the other hand, is called sometimes empty, Nothing, Bottom or Bot and is the logical equivalent of False. It has no values at all, and an expression of this type can be cast to (i.e is subtype of) any type. This is the empty set. Note that if someone tells you "the value of the expression foo() belongs to the empty set" it is highly informative - it tells you that this expression will never complete its normal execution; it will abort, throw or hang. It is the exact opposite of void.
So the following does not make sense (pseudo-C++, since noreturn is not a first-class C++ type)
void foo();
(noreturn)5; // obviously a lie; the expression 5 does "return"
(noreturn)foo(); // foo() returns void, and therefore returns
But the assignment below is perfectly legitimate, since throw is understood by the compiler to not return:
void f(int y) {
int x = y!=0 ? 100/y : throw exception();
cout << x << endl;
}
In a perfect world, you could use noreturn as the return value for the function raise() above:
noreturn raise() { throw exception(); }
...
int x = y!=0 ? 100/y : raise();
Sadly C++ does not allow it, probably for practical reasons. Instead it gives you the ability to use [[ noreturn ]] attribute which helps guiding compiler optimizations and warnings.