Why won't this c++ lamba function compile? - c++

Why does this fail to compile:
int myVar = 0;
myVar ? []()->void{} : []()->void{};
with following error msg:
Error 2 error C2446: ':' : no conversion from 'red_black_core::`anonymous-namespace'::< lambda1>' to red_black_core::anonymous-namespace::< lambda0>
While this complies correctly:
void left()
{}
void right()
{}
int myVar = 0;
myVar ? left() : right();

The return type of the ?: operator has to be deduced from it's two operands, and the rules for determining this type are quite complex. Lambdas don't satisfy them because they can't be converted to each other. So when the compiler tries to work out what the result of that ?: is, then there can't be a result, because those two lambdas aren't convertible to each other.
However, when you try to compute the functions, then you actually called them, but you didn't call the lambdas. So when you call the functions, they both have void, so the return type of ?: is void.
This
void left()
{}
void right()
{}
int myVar = 0;
myVar ? left() : right();
is equivalent to
int myVar = 0;
myVar ? [](){}() : [](){}();
Note the extra () on the end- I actually called the lambda.
What you had originally is equivalent to
compiler_deduced_type var;
if (myVar)
var = [](){};
else
var = [](){};
But- no type exists that can be both lambdas. The compiler is well within it's rights to make both lambdas different types.
EDIT:
I remembered something. In the latest Standard draft, lambdas with no captures can be implicitly converted into function pointers of the same signature. That is, in the above code, compiler_deduced_type could be void(*)(). However, I know for a fact that MSVC does not include this behaviour because that was not defined at the time that they implemented lambdas. This is likely why GCC allows it and MSVC does not- GCC's lambda support is substantially newer than MSVC's.

Rules for conditional operator in the draft n3225 says at one point
Otherwise, the result is a prvalue. If the second and third operands do not have the same type, and either
has (possibly cv-qualified) class type, overload resolution is used to determine the conversions (if any) to be
applied to the operands (13.3.1.2, 13.6). If the overload resolution fails, the program is ill-formed. Otherwise,
the conversions thus determined are applied, and the converted operands are used in place of the original
operands for the remainder of this section.
Up to that point, every other alternative (like, convert one to the other operand) failed, so we will now do what that paragraph says. The conversions we will apply are determined by overload resolution by transforming a ? b : c into operator?(a, b, c) (an imaginary function call to a so-named function). If you look what the candidates for the imaginary operator? are, you find (among others)
For every type T , where T is a pointer, pointer-to-member, or scoped enumeration type, there exist candidate operator functions of the form
T operator?(bool, T , T );
And this includes a candidate for which T is the type void(*)(). This is important, because lambda expressions yield an object of a class that can be converted to such a type. The spec says
The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator.
The lambda expressions can't be convert to any other of the parameter types listed, which means overload resolution succeeds, finds a single operator? and will convert both lambda expressions to function pointers. The remainder of the conditional opreator section will then proceed as usual, now having two branches for the conditional operator having the same type.
That's why also your first version is OK, and why GCC is right accepting it. However I don't really understand why you show the second version at all - as others explained, it's doing something different and it's not surprising that it works while the other doesn't (on your compiler). Next time, best try not to include useless code into the question.

Because every lambda is a unique type. It is basically syntactic sugar for a functor, and two separately implemented functors aren't the same type, even if they contain identical code.
The standard does specify that lambdas can be converted to function pointers if they don't capture anything, but that rule was added after MSVC's lambda support was implemented.
With that rule, however, two lambdas can be converted to the same type, and so I believe your code would be valid with a compliant compiler.

Both snippets compile just fine with GCC 4.5.2.
Maybe your compiler has no (or partial/broken) support to C++0x features such as lambda?

It doesn't fail to compile. It works just fine. You probably don't have C++0x enabled in your compiler.
Edit:
An error message has now been added to the original question! It seems that you do have C++0x support, but that it is not complete in your compiler. This is not surprising.
The code is still valid C++0x, but I recommend only using C++0x features when you really have to, until it's standardised and there is full support across a range of toolchains. You have a viable C++03 alternative that you gave in your answer, and I suggest using it for the time being.
Possible alternative explanation:
Also note that you probably didn't write what you actually meant to write. []()->void{} is a lambda. []()->void{}() executes the lambda and evaluates to its result. Depending what you're doing with this result, your problem could be that the result of calling your lambda is void, and you can't do much with void.

Related

What does static_cast mean when it's followed by two pairs of parentheses?

What does this say:
return static_cast<Hasher &>(*this)(key);
?
I can't tell whether *this or key is passed to static_cast. I looked around and found this answer, but unlike what I'm stuck on, there's nothing inside the first pair of parentheses.
The statement is parsed as
return (static_cast<Hasher &>(*this))(key);
So, the argument to static_cast is *this. Then the result of the cast, let's call it x, is used as postfix-expression in a function call with key as argument, i.e. x(key), the result of which is returned.
I can't tell whether *this or key is passed to static_cast
If you're unsure, you can just look up the syntax.
In the informal documentation, the only available syntax for static_cast is:
static_cast < new-type > ( expression )
and the same is true in any standard draft you compare.
So there is no static_cast<T>(X)(Y) syntax, and the only possible interpretation is:
new-type = Hasher&
expression = *this
and the overall statement is equivalent to
Hasher& __tmp = static_cast<Hasher &>(*this);
return __tmp(key);
In the skarupke/flat_hash_map code you linked, the interpretation is that this class has a function call operator inherited from the private base class Hasher, and it wants to call that explicitly - ie, Hasher::operator() rather than any other inherited operator(). You'll note the same mechanism is used to explicitly call the other privately-inherited function call operators.
It would be more legible if it used a different function name for each of these policy type parameters, but then you couldn't use std::equal_to directly for the Equal parameter, for example.
It might also be more legible if it used data members rather than private inheritance for Hasher, Equal etc. but this way is chosen to allow the empty base-class optimization for stateless policies.

Is it true that when passing an argument to a function, it is like assigning the value to the parameter?

I am new to C++ and I am writing pseudo code here:
void fn(a) {}
fn(b)
It is correct to assume that in the function body fn what happens is this assignment
`a = b`
I know we can pass the reference/pointer instead of just the value. I get it. But at its core, it still does this assignment of parameter = argument right?
I would like to know:
if there is any official term for this?
when exactly does this assignment happen and what exactly makes this happen? is it the compiler?
if there is any official term for this?
The official semantics of a function call are discussed in the “Function call” section of the C standard. There is no term specifically for the assignments of values to parameters.
C++ 2017 draft N4659 8.2.2 “Function call” [expr.call] 4 says:
When a function is called, each parameter (11.3.5) shall be initialized (11.6, 15.8, 15.1) with its corresponding argument…
when exactly does this assignment happen and what exactly makes this happen? is it the compiler?
It happens when a function is called. The compiler is responsible for generating code that produces a program that performs the semantics of the source code (as defined by the C++ standard).
The C++ standard describes an execution environment, the results of various types of statements and the results of various types of expressions. A compiler is only required to produce code that, when,run, produces results as-if it were run on that described execution environment.
In terms of your actual question, that means that a function call in source code does not necessarily translate into any sort of call or jump instruction when run on actual hardware.
For example, given the function:
int sqr(int x, inty)
{
return x*y;
}
a compiler might well simply compute such a result in-place and not perform any sort of parameter passing. But whether you can actually count on that behavior is a detail left up to the compiler implementor.
All that being said, on actual hardware and without inlining, a function call's parameters are very much like any other variable initialization (think copy rather than assign). The exact details (such as order of parameter evaluation) are left up to each implementation.

Why is a [[noreturn]] function checked for return type?

Suppose I have a function with signature [[noreturn]] void die(int exit_code);. If I write the statement:
check_some_condition() or die(EXIT_FAILURE);
I get an error message (with GCC 5.4.0):
error: expression must have bool type (or be convertible to bool)
but why is the type checked, if the compiler knows that going into that function, the return value won't matter; and if the condition checks out, again the return type doesn't matter?
Edit: Does the wording of the standard regarding [[noreturn]] not address this point, i.e. relax the requirements regarding types so as to "legitimize" such expressions?
The concept you are looking for is called a bottom type. In a type system, a bottom type is a type that is convertible to any other type. (Also compare it with a top type, to which all types are convertible.)
The bottom type is a perfect candidate for a function that doesn't return. It's type-safe to assign it to anything, precisely because the assignment will never happen anyway. If C++ had a bottom type, and if you declared your function as returning the bottom type, your snippet could have been perfectly legal and your expectation would have been correct.
Unfortunately, C++ doesn't have such a type. As pointed out already, [[noreturn]] is not a type -- it's an attribute that's used to express an intention (to other programmers and to the optimizer) in a way that's orthogonal to the type system. As far as the type checker is concerned, the function's return type is still void and that can't be converted to a boolean.
noreturn doesn't tell the compiler that the function returns no value. It tells the compiler that the function will not return. It also has no effect on the function's return type.
In an expression, the compiler is required to check that operands of expressions have valid types. In an expression like check_some_condition() or die(EXIT_FAILURE), that requires the return type of both check_some_condition() and die() to be checked. noreturn does not affect the function's return type, so does not affect the need for that check. If the function returns void, the expression is invalid.
Every expression must have a well determined type, period. So even though the function doesn't return, it must still be possible to evaluate the type of the expression check_some_condition() or die(EXIT_FAILURE)
And from that it follows that the function return type must be viable for use in a logical operation.

What is meant by 'use of a function'

$3.6.1/3 states-
"The function main shall not be used
(3.2) within a program.".
The sample academically motivated program below uses the name 'main' in a couple of ways which I thought are legitimate. This is based on the assumption that 'usage of a function' is related to calling the function (directly/indirectly).
struct MyClass{
private:
MyClass(){}
friend int main();
};
int main(){
MyClass m;
int (*p)() = main; // but don't do anything
}
Fair enough, the code shown compiles with gcc/VS 2010.
I am surprised by Comeau's error.
Comeau online gives error while declaration 'p' (i.e while taking address of 'main') but not while declaraing 'main' as a friend.
Who/What is right with respect to C++03?
C++03 §3.2/2 says:
An object or non-overloaded function is used if its name appears in a potentially-evaluated expression.
It goes on to list what constitutes use of other various types of entities; this is the important one here.
A friend declaration is not an expression.
When the function main() is converted to a pointer and that pointer is assigned to p, that is an expression and it is potentially evaluated (C++03 §3.2/2):
An expression is potentially evaluated unless it appears where an integral constant expression is required (see 5.19), is the operand of the sizeof operator (5.3.3), or is the operand of the typeid operator and the expression does not designate an lvalue of polymorphic class type (5.2.8).
C++03 Appendix C.1 on C++ and ISO C Compatibility says:
Changes in 3.6
Change: Main cannot be called recursively and cannot have its address taken
Rationale: The main function may require special actions.
Effect on original feature: Deletion of semantically well-defined feature
Difficulty of converting: Trivial: create an intermediary function such as mymain(argc, argv.
How widely used: Seldom
Going by the exact wording ("shall not be used"), I would think that the first example is considered legal because it doesn't use the function in any way. It adds some kind of reference to it somewhere and allows the function to access the private data. It doesn't use main(), it provides more access to it.
The second example (taking the address) actually uses main() as a symbol, by taking the address of it and placing that into a pointer to a function. Not only will that allow you to easily break the rule of not calling main from within the program, it has to interact with it (at least the info that tells where main is at).
I think that in the first case, the friend function just refers to "some function called main" while in the second case its rather "oh, you mean THE ONE main? I can't allow that".

What's the -complete- list of kinds of automatic type conversions a C++ compiler will do for a function argument?

Given a C++ function f(X x) where x is a variable of type X, and a variable y of type Y, what are all the automatic/implicit conversions the C++ compiler will perform on y so that the statement "f(y);" is legal code (no errors, no warnings)?
For example:
Pass Derived& to function taking Base& - ok
Pass Base& to function Derived& - not ok without a cast
Pass int to function taking long - ok, creates a temporary long
Pass int& to function taking long& - NOT ok, taking reference to temporary
Note how the built-in types have some quirks compared to classes: a Derived can be passed to function taking a Base (although it gets sliced), and an int can be passed to function taking a long, but you cannot pass an int& to a function taking a long&!!
What's the complete list of cases that are always "ok" (don't need to use any cast to do it)?
What it's for: I have a C++ script-binding library that lets you bind your C++ code and it will call C++ functions at runtime based on script expressions. Since expressions are evaluated at runtime, all the legal combinations of source types and function argument types that might need to be used in an expression have to be anticipated ahead of time and precompiled in the library so that they'll be usable at runtime. If I miss a legal combination, some reasonable expressions won't work in runtime expressions; if I accidently generate a combination that isn't legal C++, my library just won't compile.
Edit (narrowing the question):
Thanks, all of your answers are actually pretty helpful. I knew the answer was complicated, but it sounds like I've only seen the tip of the iceberg.
Let me rephrase the question a little then to limit its scope then:
I will let the user specify a list of "BaseClasses" and a list of "UserDefinedConversions". For Bases, I'll generate everything including reference and pointer conversions. But what cases (const/reference/pointer) can I safely do from the UserDefined Conversions list? (The user will give bare types, I will decorate with *, &, const, etc. in the template.)
C++ Standard gives the answer to your question in 13.3.3.1 Implicit conversion sequences, but it too large to post it here. I recommend you to read at least that part of C++ Standard.
Hope this link will help you.
Unfortunately the answer to your question is hugely complex, occupying at least 9 pages in the ISO C++ standard (specifically: ~6 pages in "3 Standard Conversions" and ~3 pages in "13.3.3.1 Implicit Conversion Sequences").
Brief summary: A conversion that does not require a cast is called an "implicit conversion sequence". C++ has "standard conversions", which are conversions between fundamental types (such as char being promoted to int) and things such as array-to-pointer decay; there can be several of these in a row, hence the term "sequences". C++ also permits user-defined conversions, which are defined by conversion functions and converting constructors. The important thing to note is that an implicit conversion sequence can have at most one user-defined conversion, with optionally a sequence of standard conversions on either side -- C++ will never "chain" more than one user-defined conversion together without a cast.
(If anyone would like to flesh this post out with the full details, please go ahead... But for me, that would just be too exhausting, sorry :-/)
Note how the built-in types have some
quirks compared to classes: a Derived
can be passed to function taking a
Base (although it gets sliced), and an
int can be passed to function taking a
long, but you cannot pass an int& to a
function taking a long&!!
That's not a quirk of built-in vs. class types. It's a quirk of inheritance.
If you had classes A and B, and B had a conversion to A (either because A has a constructor taking B, or because B has a conversion operator to A), then they'd behave just like int and long in this respect - conversion can occur where a function takes a value, but not where it takes a non-const reference. In both cases the problem is that there is no object to which the necessary non-const reference can be taken: a long& can't refer to an int, and an A& can't refer to a B, and no non-const reference can refer to a temporary.
The reason the base/derived example doesn't encounter this problem because a non-const Base reference can refer to a Derived object. The fact that the types are user-defined is a necessary but not a sufficient condition for the reference to be legal. Convertible user-defined classes where there is no inheritance behave just like built-ins.
This comment is way too long for comments, so I've used an answer. It doesn't actually answer your question, though, other than to distinguish between:
"Conversions" where a reference to a derived class is passed to a function taking a reference to a base class.
Conversions where a user-defined or built-in conversion actually creates an object, such as from int to long.