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

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.

Related

Do all C++ operators return something?

All C++ operators that I have worked with return something, for example the + operator returns the result of the addition.
Do all C++ operators return something, or are there some C++ operators that do not return anything?
No, not all operators return something.
Although they are probably not exactly what you are thinking about, note that the delete and delete[] C++ 'keywords' are actually operators; and they are defined as having the void return type - which means they evaluate to nothing (which is not 'something').
From cppreference:
void operator delete ( void* ptr ) noexcept;
void operator delete[]( void* ptr ) noexcept;
Operators of custom types can be overloaded to do the most weirdest things.
for example the + operator returns the result of the addition.
Not necessarily:
#include <iostream>
struct foo {
int value = 0;
void operator+(int x) {
value += x;
}
};
int main () {
foo f;
f + 3;
}
Here operator+ adds the left hand side to the value member, and its return type is void. This is a made-up example, but, in general, not returning something from a custom operator is not unusual.
The only operator that can be overloaded and that has the requirement of returning something, that I am aware of, is operator->. It must either return a raw pointer or an object that has an operator->.
To nitpick, operators don't return anything. They are just lexical elements that we use to create expressions in the language. Now, expressions have types and may evaluate to values, and I assume this is what you mean by operators "returning things".
And, well, yes. There are C++ expressions with type void (and consequentially don't evaluate to any value). Some are obvious, others less so. A nice example would be
throw std::runtime_error()
throw is an expression under the C++ grammar. You can use it in other expressions, for instance in the conditional expression
return goodStatus() ? getValue() : throw std::runtime_error();
And the type of a throw expression, is void. Obviously since this just causes execution to rapidly go elsewhere, the expression has no value.
None of the built-in C++ operators return something. Overloaded C++ operators return something insofar that the operator notation is a syntactic sugar for a function call.
Rather, operators all evaluate to something. That something has a well-defined value as well as a type. Even the function call operator void operator()(/*params*/) is a void type.
For example, +'a' is an int type with the value of 'a' encoded on your platform.
If your question is "Can C++ operators have a void return type?" then the answer is most certainly yes.
You can actually define a function call operator to return nothing. For example:
struct Task {
void operator()() const;
};
operator void(): user defined conversion function to void
You may define the peculiar operator void() conversion function, where the compiler will even warn you that the T to void conversion function will never be used:
#include <iostream>
struct Foo {
operator void() { std::cout << "Foo::operator void()!"; }
// warning: conversion function converting 'Foo' to
// 'void' will never be used
};
int main() {
Foo f;
(void)f; // nothing
f.operator void(); // Foo::operator void()!
}
as governed by [class.conv.fct]/1
[...] A conversion function is never used to convert a (possibly
cv-qualified) object to the (possibly cv-qualified) same object
type (or a reference to it), to a (possibly cv-qualified) base class
of that type (or a reference to it), or to (possibly cv-qualified)
void.117
(117)
These conversions are considered as standard conversions for the
purposes of overload resolution ([over.best.ics], [over.ics.ref]) and
therefore initialization ([dcl.init]) and explicit casts. A
conversion to void does not invoke any conversion function
([expr.static.cast]). Even though never directly called to perform a
conversion, such conversion functions can be declared and can
potentially be reached through a call to a virtual conversion function
in a base class.
Whilst, however, as is shown above, you can still invoke it using the explicit .operator void() syntax.
The operators defined (builtin) by the language are tokens used to perform different kinds of computations:
arithmetic (+,-,*,/)
increment/decrement (++,--)
assignment (=,+=,-=,*=,/=,%=,>>=,<<=,&=,^=,|=)
logic (!,&&,||)
relational (==,!=,>,<,>=,<=)
conditional ?
comma
and so on. The list can be very extensive.
In language references like this one or this one, these are not necessarily referenced as returning something, just performing an arithmetic or logic operation, a comparison by which means a variable may be modified, etc.
Since this operation results in some value, it may be interpreted as been "returned" by the operator, but it is different from a function return value.
The overloaded operators, on the other hand, can be defined with a return value of some type, even that can be void, so, no, not all operators return some value in C++.
I'm assuming you're talking about operator functions and not operators as a syntactic unit of the language.
If you overload operators on any type, you may actually return whatever you want.
This also makes a lot of sense, because operations like * or () may sometimes very intuitively not return their input type. Imagine multiplying a complex number type with a real number type. Or an operator that returns an element from a collection.
You may also overload the ++ and -- operators to not return anything thus removing the extremely error-prone mixing of side-effect and expression value that the standard version has.
No.
Consider these two examples here:
int multiply (int a, int b) {
return a*b;
}
void multiply_void(int a, int b) {
cout << a*b;
//or cout << multiply(a,b);
}
First function will return an integer value which can be used by another function.
The value is returned and stored in memory to be used when necessary. If not, it is not visible to human & just sits happily in the memory.
Second function will output to the default output device(usually console).
The value returned by the multiplication operator is passed to an output device.
The function multiply_void does not return an actual value.
All operators return something. They are called operators because they operate something , therefore they will return something. Those Operators who do not return something cant be called operators. Either they will return some value or return True or False depending upon the situation.
Operators on their own do not necessarily return anything. Function calls return values. Operators can result in values.
Operators can sometimes invoke functions. Examples include:
• The function call operator.
• An overloaded operator that gets transformed into a function call.
• operator new, which is invoked as part of a new-expression, is a function call.
My only purpose in mentioning function calls is to clarify the result vs. return. Based on looking at all 126 instances of “return” and words derived from it in [expr], the section seems to carefully use the word return to refer to:
• the result of a function call
• aspects of control flow related to coroutines
OK, that’s enough pedantry on result vs. return.
C++ Operators return something or not is depends upon how you used them. Built-In C++ operators return some value until and unless enforced to return void.

How does a complex C style type casting expression work?

I was looking for a way to uppercase a standard string. The answer that I found included the following code:
int main()
{
// explicit cast needed to resolve ambiguity
std::transform(myString.begin(), myString.end(), myString.begin(),
(int(*)(int)) std::toupper)
}
Can someone explain the casting expression “(int(*) (int))”? All of the other casting examples and descriptions that I’ve found only use simple type casting expressions.
It's actually a simple typecast - but to a function-pointer type.
std::toupper comes in two flavours. One takes int and returns int; the other takes int and const locale& and returns int. In this case, it's the first one that's wanted, but the compiler wouldn't normally have any way of knowing that.
(int(*)(int)) is a cast to a function pointer that takes int (right-hand portion) and returns int (left-hand portion). Only the first version of toupper can be cast like that, so it disambiguates for the compiler.
(int(*)(int)) is the name of a function pointer type. The function returns (int), is a function *, and takes an (int) argument.
As others already mentioned, int (*)(int) is the type pointer to a function which takes and returns int. However what is missing here is what this cast expression does: Unlike other cast expressions it does not really cast (i.e. it does not convert a value into a different type), but it selects from the overloaded set of functions named std::toupper the one which has the signature int(int).
Note, however, that this method is somewhat fragile: If for some reason there's no matching function (for example because the corresponding header was not included) but only one non-matching function (so no ambiguity arises), then this cast expression will indeed turn into a cast, more exactly a reinterpret_cast, with undesired effects. To make sure that no unintended cast happens, the C++ style cast syntax should be used instead of the C style cast syntax: static_cast<int(*)(int)>(std::toupper) (actually, in the case of std::toupper this case cannot occur because the only alternative function is templated and therefore ambiguous, however it could happen with other overloaded functions).
Coincidentally, the new-style cast syntak is more readable in that case, too.
Another possibility, which works without any cast expression, is the following:
int (*ptoupper)(int) = &std::toupper; // here the context provides the required type information
std::transform(myString.begin(), myString.end(), myString.begin(), ptoupper);
Note that the reason why the context cannot provide the necessary information is that std::transform is templated on the last argument, therefore the compiler cannot determine the correct function to choose.
int function(int);
A function taking int and returning int.
int (*function_pointer)(int);
A pointer to a function taking int and returning int.
int (*)(int)
The type of a pointer to a function taking int and returning int.
std::toupper from <cctype> already has type int (*)(int), but the one in <locale> is templatized on charT, which I assume is the reason for the cast. But ptr_fun would be clearer.

error: lvalue required while operator overloading ++/-- etc

I transferred my code to Ubuntu 4.4.1 g++ compiler. While overloading operator ++ (int) as below, it throws error for (T*), but works fine for (T*&). In my earlier version (linux-64, but don't remember exact version) it was working fine with (T*) also.
Any reason, why ?
template<typename T>
struct Wrap
{
void *p; // Actually 'p' comes from a non-template base class
Wrap<T>& operator ++ ()
{
((T*)p) ++; // throws error; if changed to (T*&) then ok!
return *this;
}
// ...
};
int main ()
{
Wrap<int> c;
++c; // calling prefix increment
}
A result of a type-cast is not an lvalue, so it cannot be assigned to and (built-in) ++ is a form of assignment. It was a bug in the compiler if it ever worked.
With reference it compiles (in efect it's the same as *(T**)&p), but due to aliasing rules (compiler may assume that pointers (and references) of different types don't point to the same object) it is formally invalid, though it will work on all known compilers.
The cleanest way it to:
p = static_cast<void *>(static_cast<T *>(p) + 1)
(never use C-style cast in C++) and rely on the compiler being able to compile it exactly the same way as ++. However if you have the template argument available when defining the pointer (in the sample code you do), it's much better to just use properly typed pointer (I'd say it would also work with member pointers, but they don't have meaningful ++).
Looks like you mixing up your prefix and postfix increment signatures. Also, why use a void* if you know your type is T ?
See below for appropriate signatures:
http://www.codeguru.com/forum/showthread.php?t=231051

Why does my function pointer code run with no errors?

I have this:
typedef void (*funcptr) (void);
int main(){
funcptr(); //this can compile and run with no error . WHAT DOES IT MEAN? WHY NO ERRORS?
}
The statement creates a funcptr instance by its default constructor* and discard it.
It is just similar to the code
int main () {
double();
}
(Note: * Technically it performs default-initialization as not all types have constructors. Those types will return the default value (zero-initialized), e.g. 0. See C++98 §5.2.3/2 and §8.5/5 for what actually happens.)
In C++ language, any expression of the form some_type() creates a value of type some_type. The value is value-initialized.
For example, expression int() creates a value-initialized value of type int. Value-initialization for int means zero initialization, meaning that int() evaluates to compile-time integer zero.
The same thing happens in your example. You created a value-initialized value of type funcptr. For pointer types, value-initialization means initialization with null-pointer.
(Note also, that it is absolutely incorrect to say that expressions like int(), double() or the one in your OP with non-class types use "default constructors". Non-class types have no constructors. The concept of initialization for non-class types is defined by the language specification without involving any "constructors".)
In other words, you are not really "playing with function pointer" in your code sample. You are creating a null function pointer value, but you are not doing anything else with it, which is why the code does not exhibit any problems. If you wanted to attempt a call through that function pointer, it would look as follows funcptr()() (note two pairs of ()), and this code would most certainly crash, since that's what usually happens when one attempts a call through a null function pointer value.
You are defining a datatype, funcptr, which is a function that takes no parameters and returns void. You are then creating an instance of it, but without an identifier, discarding it.

Premature optimization or am I crazy?

I recently saw a piece of code at comp.lang.c++ moderated returning a reference of a static integer from a function. The code was something like this
int& f()
{
static int x;
x++;
return x;
}
int main()
{
f()+=1; //A
f()=f()+1; //B
std::cout<<f();
}
When I debugged the application using my cool Visual Studio debugger I saw just one call to statement A and guess what I was shocked. I always thought i+=1 was equal to i=i+1 so
f()+=1 would be equal to f()=f()+1 and I would be seeing two calls to f(), but I saw only one. What the heck is this? Am I crazy or is my debugger gone crazy or is this a result of premature optimization?
This is what The Standard says about += and friends:
5.17-7: The behavior of an expression of the form E1 op= E2 is equivalent to
E1 = E1 op E2 except that E1 is
evaluated only once.[...]
So the compiler is right on that.
i+=1 is functionally the same as i=i+1. It's actually implemented differently (basically, it's designed to take advantage of CPU level optimization).
But essencially the left side is evaluated only once. It yields a non-const l-value, which is all it needs to read the value, add one and write it back.
This is more obvious when you create an overloaded operator for a custom type. operator+= modifies the this instance. operator+ returns a new instance. It is generally recommended (in C++) to write the oop+= first, and then write op+ in terms of it.
(Note this is applies only to C++; in C#, op+= is exactly as you assumed: just a short hand for op+, and you cannot create your own op+=. It is automatically created for you out of the Op+)
Your thinking is logical but not correct.
i += 1;
// This is logically equivalent to:
i = i + 1;
But logically equivalent and identical are not the same.
The code should be looked at as looking like this:
int& x = f();
x += x;
// Now you can use logical equivalence.
int& x= f();
x = x + 1;
The compiler will not make two function calls unless you explicitly put two function calls into the code. If you have side effects in your functions (like you do) and the compiler started adding extra hard to see implicit calls it would be very hard to actually understand the flow of the code and thus make maintenance very hard.
f() returns a reference to the static integer. Then += 1 adds one to this memory location – there's no need to call it twice in statement A.
In every language I've seen which supports a += operator, the compiler evaluates the operand of the left-hand side once to yield some type of a address which is then used both to read the old value and write the new one. The += operator is not just syntactic sugar; as you note, it can achieve expression semantics which would be awkward to achieve via other means.
Incidentally, the "With" statements in vb.net and Pascal both have a similar feature. A statement like:
' Assime Foo is an array of some type of structure, Bar is a function, and Boz is a variable.
With Foo(Bar(Boz))
.Fnord = 9
.Quack = 10
End With
will compute the address of Foo(Bar(Boz)), and then set two fields of that structure to the values nine and ten. It would be equivalent in C to
{
FOOTYPE *tmp = Foo(Bar(Boz));
tmp->Fnord = 9;
tmp->Quack = 10;
}
but vb.net and Pascal do not expose the temporary pointer. While one could achieve the same effect in VB.net without using "With" to hold the result of Bar(), using "With" allows one to avoid the temporary variable.