Forbidden syntax for pointer/reference to bound member function - c++

Suppose I have the following:
struct A {
int foo(int bar) const { return bar; }
};
and I want to specify a name that refers to a "bound" member function (i.e.):
A a;
auto opt1 = a.foo; // Forbidden, instead do something like...
auto opt2 = [&a] (int i) { return a.foo(i); }; // or ...
auto opt3 = std::bind(&A::foo, a, std::placeholders::_1);
it is then simple to invoke the bound member function:
assert(opt1(42) == 42); // If 'opt1' were allowed
assert(opt2(42) == 42);
assert(opt3(42) == 42);
In my view, opt1 would be the preferred solution to achieve the goal. However, specifying a bound function via opt1 is forbidden by the language.
My question is purely legal: What part of the C++(20) standard forbids a construct like opt1? My question is not why, but where.

[expr.ref]:
[for the expression E1.E2]....if E1.E2 refers to a non-static member function...The expression can be used only as the left-hand operand
of a member function call.

Related

Accessing captured variables through explicit this parameter in lambda

From declarations / functions / 9.3.4.6 / 6.2 (i apologize on how to cite the specific sentence from standard):
An explicit-object-parameter-declaration is a parameter-declaration with a this specifier. An explicit-object-parameter-declaration shall appear only as the first parameter-declaration of a parameter-declaration-list of either: (6.1) a member-declarator that declares a member function ([class.mem]), or (6.2) a lambda-declarator ([expr.prim.lambda]).
If this as explicit object parameter is permitted from lambda expressions, what will happen when we capture variables at the same time?
Based on my understandings, if we have lambda under the hood:
[x = 2](this auto& func) { x = 4; }();
may have the rough equivalent of:
class lambda01 {
private:
int x;
public:
constexpr lambda01(cons int& x_)
: x{x_} {}
constexpr void operator()(this lambda01& func) {
func.x = 4;
}
};
lambda04 lambda04_obj {2};
lambda04_obj.operator()();
if it's right.
For example no. 1:
int x;
// is it:
[&x](this auto& func){ x = 4; }();
assert(x == 4);
// or:
[&x](this auto& func){ func.x = 2; }();
assert(x == 2);
Are both expressions valid?
Is lambda taking l-value object parameter valid?
For example no. 2 that will print arguments in variadic:
[]<typename... Args>(const Args&... args) {
[&](this auto func){
/** ... **/
};
}(1, 2, 3, 4);
From the commented expression, which one is valid?
(std::cout << args << '\n', ...)
(std::cout << func.args << '\n', ...)
both
neither
If the second choice is valid, then that would deserve another question regarding the possible parameter packs in 1 object.
In short, is it valid to use captured variables accessed with dot operator in lambda taking explicit object parameter?
The standard doesn't allow it:
For each entity captured by copy, an unnamed non-static data member is declared in the closure type.
If it's "unnamed", then you can't name it. There's specific language that causes the name of a captured entity to be transformed into a this-based expression, but that's it.
So you can take an explicit this parameter, and names of captured entities will automatically use that. But you can't access those variables through the explicit parameter.
The only reason to explicitly take this in a lambda is to use the interfaces the standard provides: calling the lambda. AKA: recursively calling the lambda without naming the lambda.

Examples of mandatory type deduction in C++

Google's C++ Style Guide at some point states:
There are several contexts in which C++ allows (or even requires) types to be deduced by the compiler.
What are some examples of mandatory type deduction?
A simple example is initialisation of a lambda variable. The type of the lambda is anonymous, therefore it cannot be named explicitly and must be deduced:
auto var = [capture]{};
Another example:
struct {
int x, y;
} g_xy;
Here g_xy is a global variable of unnamed type. If you try to return it for example you have to let the compiler deduce the return type of the function because you cannot name it:
auto foo()
{
return g_xy;
}
Although possible unnamed types (except lamdas) are rarely useful and used.
The style guide gives several examples where the compiler does automatic type deduction. The most obvious case is whenever you use the auto keyword, introduced with C++11. auto is a placeholder for an actual type. Whenever you use auto the compiler will deduce the type from: the type of expression used to intialise a variable; the trailing type or type of return expression of a function.
Normally you would declare a variable like this:
int i = 0;
where you specify the type int for the variable i. However, in modern C++ you could declare variables without specifying their type and the compiler will deduce their types automatically:
auto a = 42; // a is an int
auto& b = a; // b is an int&
auto c = b; // c is an int
auto d{42}; // d is an int, not a std::initializer_list<int>
auto v = {1, 2, 3}; //v is a std::initializer_list<int>
Other examples include a named lambda function:
auto lower = [] (const char c) { return tolower(c); };
and in C++14 onward, a generic lambda where both the return type and lambda parameters can be auto:
auto add = [](const auto a, const auto b) { return a + b; }
One thing to note is that auto is a placeholder for type, not for const, volatile or reference specifers.
Some advantages of using auto include:
variable is always initialised
ensure the correct type is used without any implicit conversion
less typing and concern for actual type
And yet another example - type of generic lambdas with auto arguments can not be specified.
auto lam = [](auto v) { }
There is no way to specify type of v in invocation of lambda.

Result of decltype in const methods

The C++11 decltype returns the type of the expression given to it (mostly). But this can differ from the type of the expression as it is actually accessible:
template<typename T>
struct Ref {
Ref(T&) { }
};
#define GETTYPE decltype
//#define GETTYPE typeof
struct Problem {
void doit_c() const { Ref<GETTYPE(n)> rn{n}; }
void doit_nc() { Ref<GETTYPE(n)> rn{n}; }
int n;
};
int main() {
int i;
const int ci = 0;
Problem pr;
// decltype == typeof == int
Ref<GETTYPE(i)> ri{i};
pr.doit_nc();
// decltype == typeof == const int
Ref<GETTYPE(ci)> rci{ci};
Ref<GETTYPE(static_cast<const int&>(i))> rcci{static_cast<const int&>(i)};
// typeof == const int, decltype == int (!)
pr.doit_c();
return 0;
}
In the example, the Ref struct is just used to cause a compile error if T does not match the actual constructor argument. The Problem::doit_c() method is where decltype(n) returns a non-const result, even though n is const in this context.
If one switches from the standard decltype to the GNU extension typeof, this seems to take the const-ness of the method into account.
Now my question: Is there a C++11 / C++14 / C++17 compliant alternative to decltype() / typeof() that behaves "correctly" (as in: no compile error above) for expressions like the declaration in the const-method above?
Edited:
Simplified the first sentence to remove some errors and stop distracting from the point of the question (thanks, #skypjack)
Simplified the use use of macros in the example code (thanks, #Richard Critten)
decltype is a feature that kinda sits at two chairs at once. Firstly, as the name suggests, it can give you the exact declared type of an entity, ignoring the context in which it is used. Secondly, it can treat its argument as an expression, whose exact type depends on the context and its value category.
decltype applied directly to a "naked" (unparenthesized) class member access is a special case, in which decltype acts in accordance with its first role. It will not treat n as an expression. Instead it will produce the type of that class member, ignoring the context.
If you want it to treat n as an expression, you have to parenthesize it
struct Problem {
void doit_c() const
{
Ref<decltype(n)> rn1{n}; // `decltype(n)` is `int` -> ERROR
Ref<decltype((n))> rn2{n}; // `decltype((n))` is `const int &` -> compiles OK
}
};
You can find out the effective cv-qualified type of n using a temporary reference:
void doit_c() const { auto& x = n; Ref<GETTYPE(x)> rn{n}; }
void doit_nc() { auto& x = n; Ref<GETTYPE(x)> rn{n}; }
But it's simpler and clearer to parenthesize, as shown in AnT's answer.

Where are lambda captured variables stored?

How is it possible that this example works? It prints 6:
#include <iostream>
#include <functional>
using namespace std;
void scopeIt(std::function<int()> &fun) {
int val = 6;
fun = [=](){return val;}; //<-- this
}
int main() {
std::function<int()> fun;
scopeIt(fun);
cout << fun();
return 0;
}
Where is the value 6 stored after scopeIt is done being called? If I replace the [=] with a [&], it prints 0 instead of 6.
It is stored within the closure, which - in your code - is then stored within std::function<int()> &fun.
A lambda generates what's equivalent to an instance of a compiler generated class.
This code:
[=](){return val;}
Generates what's effectively equivalent to this... this would be the "closure":
struct UNNAMED_TYPE
{
UNNAMED_TYPE(int val) : val(val) {}
const int val;
// Above, your [=] "equals/copy" syntax means "find what variables
// are needed by the lambda and copy them into this object"
int operator() () const { return val; }
// Above, here is the code you provided
} (val);
// ^^^ note that this DECLARED type is being INSTANTIATED (constructed) too!!
Lambdas in C++ are really just "anonymous" struct functors. So when you write this:
int val = 6;
fun = [=](){return val;};
What the compiler is translating that into is this:
int val = 6;
struct __anonymous_struct_line_8 {
int val;
__anonymous_struct_line_8(int v) : val(v) {}
int operator() () const {
return val; // returns this->val
}
};
fun = __anonymous_struct_line_8(val);
Then, std::function stores that functor via type erasure.
When you use [&] instead of [=], it changes the struct to:
struct __anonymous_struct_line_8 {
int& val; // Notice this is a reference now!
...
So now the object stores a reference to the function's val object, which becomes a dangling (invalid) reference after the function exits (and you get undefined behavior).
The so-called closure type (which is the class type of the lambda expression) has members for each captured entity. Those members are objects for capture by value, and references for capture by reference. They are initialized with the captured entities and live independently within the closure object (the particular object of closure type that this lambda designates).
The unnamed member that corresponds to the value capture of val is initialized with val and accessed from the inside of the closure types operator(), which is fine. The closure object may easily have been copied or moved multiple times until that happens, and that's fine too - closure types have implicitly defined move and copy constructors just as normal classes do.
However, when capturing by reference, the lvalue-to-rvalue conversion that is implicitly performed when calling fun in main induces undefined behavior as the object which the reference member referred to has already been destroyed - i.e. we are using a dangling reference.
The value of a lambda expression is an object of class type, and
For each entity
captured by copy, an unnamed non-static data member is declared in the closure type.
([expr.prim.lambda]/14 in C++11)
That is, the object created by the lambda
[=](){return val;}
actually contains a non-static member of int type, whose value is 6, and this object is copied into the std::function object.

Function returning a lambda expression

I wonder if it's possible to write a function that returns a lambda function in C++11. Of course one problem is how to declare such function. Each lambda has a type, but that type is not expressible in C++. I don't think this would work:
auto retFun() -> decltype ([](int x) -> int)
{
return [](int x) { return x; }
}
Nor this:
int(int) retFun();
I'm not aware of any automatic conversions from lambdas to, say, pointers to functions, or some such. Is the only solution handcrafting a function object and returning it?
You don't need a handcrafted function object, just use std::function, to which lambda functions are convertible:
This example returns the integer identity function:
std::function<int (int)> retFun() {
return [](int x) { return x; };
}
For this simple example, you don't need std::function.
From standard §5.1.2/6:
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.
Because your function doesn't have a capture, it means that the lambda can be converted to a pointer to function of type int (*)(int):
typedef int (*identity_t)(int); // works with gcc
identity_t retFun() {
return [](int x) { return x; };
}
That's my understanding, correct me if I'm wrong.
Though the question specifically asks about C++11, for the sake of others who stumble upon this and have access to a C++14 compiler, C++14 now allows deduced return types for ordinary functions. So the example in the question can be adjusted just to work as desired simply by dropping the -> decltype... clause after the function parameter list:
auto retFun()
{
return [](int x) { return x; }
}
Note, however, that this will not work if more than one return <lambda>; appears in the function. This is because a restriction on return type deduction is that all return statements must return expressions of the same type, but every lambda object is given its own unique type by the compiler, so the return <lambda>; expressions will each have a different type.
You can return lambda function from other lambda function, since you should not explicitly specify return type of lambda function. Just write something like that in global scope:
auto retFun = []() {
return [](int x) {return x;};
};
You should write like this:
auto returnFunction = [](int x){
return [&x](){
return x;
}();
};
to get your return as a function, and use it like:
int val = returnFunction(someNumber);
If you do not have c++ 11 and are running your c++ code on micro controllers for example. You can return a void pointer and then perform a cast.
void* functionThatReturnsLambda()
{
void(*someMethod)();
// your lambda
someMethod = []() {
// code of lambda
};
return someMethod;
}
int main(int argc, char* argv[])
{
void* myLambdaRaw = functionThatReturnsLambda();
// cast it
auto myLambda = (void(*)())myLambdaRaw;
// execute lambda
myLambda();
}