Function pointers in C++ syntax - c++

I inspected the signature of this right part of this assignment:
creating a thread:
std::thread t2 = std::thread(&Vehicle::addID, &v2, 2);
by hovering with the mouse on and "thread" on the right I got:
std::thread::thread<...>(void (Vehicle::*&&_Fx)(int id), Vehicle &_Ax, int &&_Ax)
Now, I know the basics of C function pointers syntax.
But in C++ you see many times first the class name on the left (especially when using templates)
so I understand that - * within this syntax means a pointer to a (public) member function of the class Vehicle that take an int and returns void (nothing), but whats the && (similar to move constructor) mean?
reference to reference of / take the reference to the member function object by reference??

Notice how the lvalue argument (&v2) becomes an lvalue reference, and the rvalue arguments (the literal 2 and your &Vehicle::addID) become an rvalue reference.
The constructor template you're using is:
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );
// ^^
We can see there that we ask the computer to take the arguments by "universal reference", i.e. as referency as possible, given each one's value category.
So you're seeing the result of that.
It's not part of the type of the pointer-to-member-function: it's something that's become an rvalue-reference-to-pointer-to-member-function because that's how std::thread takes its arguments, for the purpose of being nice and generic. In the case of a function pointer it's redundant, as there's nothing to "move", but for more complex arguments this can be important.
Of course, due to the nasty "spiral rule" we inherited from C, you end up with the && confusingly plonked in the middle of the pointer's type. 🤪😭
tl;dr:
take the reference [pointer — Ed.] to the member function object by reference??
Pretty much.

Related

std::async no matching overloaded function found [duplicate]

I've noticed that it's impossible to pass a non-const reference as an argument to std::async.
#include <functional>
#include <future>
void foo(int& value) {}
int main() {
int value = 23;
std::async(foo, value);
}
My compiler (GCC 4.8.1) gives the following error for this example:
error: no type named ‘type’ in ‘class std::result_of<void (*(int))(int&)>’
But if I wrap the value passed to std::async in std::reference_wrapper, everything is OK. I assume this is because std::async takes it's arguments by value, but I still don't understand the reason for the error.
It's a deliberate design choice/trade-off.
First, it's not necessarily possible to find out whether the functionoid passed to async takes its arguments by reference or not. (If it's not a simple function but a function object, it could have an overloaded function call operator, for example.) So async cannot say, "Hey, let me just check what the target function wants, and I'll do the right thing."
So the design question is, does it take all arguments by reference if possible (i.e. if they're lvalues), or does it always make copies? Making copies is the safe choice here: a copy cannot become dangling, and a copy cannot exhibit race conditions (unless it's really weird). So that's the choice that was made: all arguments are copied by default.
But then, the mechanism is written so that it actually fails to then pass the arguments to a non-const lvalue reference parameter. That's another choice for safety: otherwise, the function that you would expect to modify your original lvalue instead modifies the copy, leading to bugs that are very hard to track down.
But what if you really, really want the non-const lvalue reference parameter? What if you promise to watch out for dangling references and race conditions? That's what std::ref is for. It's an explicit opt-in to the dangerous reference semantics. It's your way of saying, "I know what I'm doing here."
std::async (and other functions that do perfect forwarding) look at the type of the argument that you pass to figure out what to do. They do not look at how that argument will eventually be used. So, to pass an object by reference you need to tell std::async that you're using a reference. However, simply passing a reference won't do that. You have to use std::ref(value) to pass value by reference.
The issue itself is only marginally related to std::async(): When defining the result of the operation, std::async() uses std::result_of<...>::type with all its arguments being std::decay<...>::type'ed. This is reasonable because std::async() takes arbitrary types and forwards them to store them in some location. To store them, values are needed for the function object as well as for the arguments. Thus, std::result_of<...> is used similar to this:
typedef std::result_of<void (*(int))(int&)>::type result_type;
... and since int can't be bound to an int& (int isn't an lvalue type was is needed to be bound to int&), this fails. Failure in this case means that std::result_of<...> doesn't define a nested type.
A follow-up question could be: What is this type used to instantiate std::result_of<...>? The idea is that the function call syntax consisting of ResultType(ArgumentTypes...) is abused: instead of a result type, a function type is passed and std::result_of<...> determines the type of the function called when that function type is called with the given list of arguments is called. For function pointer types it isn't really that interesting but the function type can also be a function object where overloading needs to be taken into account. So basically, std::result_of<...> is used like this:
typedef void (*function_type)(int&);
typedef std::result_of<function_type(int)>::type result_type; // fails
typedef std::result_of<function_type(std::reference_wrapper<int>)>::type result_type; //OK

Differrent function signatures C++

Found some C++ tests, one of a questions: what is diff between function signatures.
Am I right with following answers?
void f(data); // 1)calls copy constructor of data to pass in function
void f(data*); // 2)data passes to function by ptr, no copy constructor called
void f(data const*); // 3)same as 2, but not allowed to change pointer, allowed to change data
void f(data* const); // 4)same as 2, but not allowed to change data, allowed to change pointer
void f(data const* const); // 5) same as 2, niether ptr and data can be changed
void f(data&); // 6) same as 2, but ref instead of ptr
void f(data const&); // 7) same as 3
void f(data&&); // 8) Refence to reference(most subtle moment to me), move constructor, depends on function original data can be erased
Not quite:
Not necessarily copy. Other constructors can be used to initialise the parameter.
and 4. are wrong way 'round.
There is no such thing as "reference to a reference". That is an rvalue reference. No constructor is called when binding a reference to a value.
As an additional statement to 8: As already mentioned here, there is no such thing like a reference to a reference (at least not as a plain fundamental C++ object/value type category). Its exact reference type depends on the usage context, but in the most cases, it's called an rvalue reference. In a non-evaluated template argument context - f being a function template and date being a typed template argument - its reference type is called forwarding reference. To stay strictly in standard terminology, it's also not a universal reference as Coy Kramer stated here since the committee didn't accept the terminology of Scott Meyers in 2015 for this for various reasons.

std::function - value vs. reference argument

Are there any practical differences between std::function for type with value parameter vs with const reference to value parameter? Consider following code:
auto foo = [] (VeryBigType i) {
};
auto bar = [] (const VeryBigType& i) {
};
std::function<void(VeryBigType)> a;
a = foo;
a = bar;
std::function<void(const VeryBigType&)> b;
b = foo;
b = bar;
This code compiles without issues and works perfeclty well. I know that passing by value vs by ref has performance differences and so foo and bar would behave differently. But are there any differences depending on std::function template type? For example, are there any implementation and/or behaviour and/or performance differences between
std::function<void(VeryBigType)>(bar) vs std::function<void(const VeryBigType&)>(bar) or these constructs are equivalent?
cppreference says that std::function<R(Args...)>::operator() has signature
R operator()(Args... args) const;
and that it calls the stored callable f basically by f(std::forward<Args>(args)...). The performance characteristics depend on both the template argument and the lambda's argument type and I think it would be helpful to just see everything that can happen. In your case, you have 2 std::function types, 2 callables, and 3 possible value categories for the argument, giving you 12 possibilities.
std::function<void(VeryBigType)> f = [](VeryBigType i) { }
If you call this with an lvalue, like
VeryBigType v;
f(v);
This will copy v into the argument of operator(), and then operator() will pass an rvalue to the lambda, which will move the value into i. Total cost: 1 copy + 1 move
If you call this with a prvalue, like
f(VeryBigType{});
Then this will materialize the prvalue into the argument of operator(), then pass an rvalue to the lambda, which will move it into i. Total cost: 1 move
If you call this with an xvalue, like
VeryBigType v;
f(std::move(v));
This will move v into the argument of operator(), which will pass an rvalue to the lambda, which will move it again into i. Total cost: 2 moves.
std::function<void(VeryBigType)> f = [](VeryBigType const &i) { }
If you call this with an lvalue, this will copy once into the argument of operator(), and then the lambda will be given a reference to that argument. Total cost: 1 copy.
If you call this with a prvalue, this will materialize it into the argument of operator(), which will pass a reference to that argument to the lambda. Total cost: nothing.
If you call this with an xvalue, this will move it into the argument of operator(), which will pass a reference to that argument to the lambda. Total cost: 1 move.
std::function<void(VeryBigType const&)> f = [](VeryBigType i) { }
If you call this with an lvalue or xvalue (i.e. with a glvalue), operator() will receive a reference to it. If you call this with a prvalue, it will be materialized into a temporary, and operator() will receive a reference to that. In any case, the inner call to the lambda will always copy. Total cost: 1 copy.
std::function<void(VeryBigType const&)> f = [](VeryBigType const &i) { }
Again, no matter what you call this with, operator() will receive just a reference to it, and the lambda will just receive the same reference. Total cost: nothing.
So, what did we learn? If both the std::function and the lambda take references, you avoid any extraneous copies and moves. Use this when possible. Putting a by-value lambda inside a by-const-lvalue-reference std::function, however, is a bad idea (unless you have to). Essentially, the lvalue reference "forgets" the value category of the argument, and the argument to the lambda is always copied. Putting a by-const-lvalue-reference lambda inside a by-value std::function is pretty good performance-wise, but you only need to do so if you're calling into other code that expects a by-value std::function, because otherwise a by-reference std::function achieves the same thing but with less copying and moving. Putting a by-value lambda inside a by-value std::function is slightly worse than putting a by-const-lvalue-reference lambda inside of it, due to an extra move in all calls. It would be better to instead take the argument of the lambda by-rvalue-reference, which is pretty much the same as taking it by-const-lvalue-reference except you still can mutate the argument, just as if you took it by value anyway.
TL;DR: By-value and rvalue-reference arguments in a std::function template argument should correspond to by-rvalue-reference or by-const-lvalue-reference arguments in the lambda you put inside the std::function. By-lvalue-reference arguments in the type should correspond to by-lvalue-reference arguments in the lambda. Anything else incurs additional copies or moves, and should only be used when needed.
Your question is confusing, because you seem to be aware that there are very large performance differences between a value and a ref argument.
What you seem to not be aware of is that the template type of the function object is what determines how arguments are passed to your lambda function, not the lambda function itself, because of the cdecl calling convention: the caller passes arguments on the stack and then performs the cleanup, and the caller calls through your std::function object.
So, a will always allocate a new copy of your object and pass a reference to it, then clean it up, and b will always pass a reference to the original object.
Edit: as to why that works regardless of how you define the lambda functions, again because of cdecl, both functions expect a pointer as the first argument and do their work on them. The rest of the declarations around the types (type sizes, constness, references etc) are only used to validate the code inside the function and validating that the function itself can be called by your function object (ie, that function will send a pointer as the first argument).

A function template using std::forward and rvalue

Given the following function template from "The C++ Programming language 4th edition":
template <typename TT, typename A>
unique_ptr<TT> make_unique(int i, A && a)
{
return unique_ptr<TT>{new TT{ i, std::forward<A>(a) }};
}
I find it difficult to understand what that actually does,
a is definitely an rvalue and therefore the make_unique function
seem to allocate its content on the heap and holding that address in a unique_ptr so we won't have to worry about deleting it. but, what does the standard library forward function does? (I guess it has something to do with a being rvalue) I tried reading at C++ documentation but I don't seem to understand that properly.
would love to get a good explanation from a more experienced C++ programmer.
thanks!
Hmmm... I'm pretty sure this isn't given as a work-around implementation of the future std::make_unique, but anyway, what the function does is pretty easy to understand, though it requires you to have prior knowledge of new C++11 features.
template <typename TT, typename A>
unique_ptr<TT> make_unique(int i, A && a)
{
return unique_ptr<TT>{new TT{ i, std::forward<A>(a) }};
}
First of all make_unique is a function template, I really hope you already know that, as the following would require that you have at least the most basic knowledge on what templates does and how templates work.
Now to the non-trivial parts. A && a there is a function parameter. Specifically, a is the function parameter whose type is A&& which is an r-value reference. With its type being a template type parameter, we can deduce its type from whatever the caller passes as an argument to a. Whenever we have r-value reference and argument type deduction, special deduction rules and reference collapsing kicks-in and we have a so-called "universal reference" which is particularly useful for perfect forwarding functions.
Whenever we have a universal reference (a in our case), we will almost always want to preserve its original "l-valueness" or "r-valueness" whenever we want to use them. To have this kind of behavior, we should almost always use std::forward (std::forward<A>(a)). By using std::forward, a variable originally passed as an l-value remains an l-value and a variable originally passed as an r-value remains an r-value.
After that, things are just simple
return unique_ptr<TT>{new TT{ i, std::forward<A>(a) }};
Notice the use of the braces. Instead of using parentheses, it is using C++11's uniform initialization syntax of calling constructors. With new TT{ i, std::forward<A>(a) }, you are dynamically allocating an object of type TT with the given parameters inside the braces. With unique_ptr<TT>{new TT{ i, std::forward<A>(a) }};, you are creating a unique_ptr<TT> whose parameter is the one returned by the dynamic allocation. The unique_ptr<TT> object now then returned from the function.
Due to template argument deduction and reference collapsing rules you cannot know if a is a rvalue reference or a lvalue reference. std::forward passes the argument to the TT contrustor exactly as it was passed to make_unique. Scott Meyers calls A&& a universal reference, because it can be a lvalue ref or an rvalue ref, depended on what is passed to make_unique.
If you pass an rvalue Foo to make_unique, std::forward passes an rvalue reference.
If you pass an lvalue Foo to make_unique, std::forward passes an lvalue reference.
make_unique(1, Foo()); // make_unique(int, A&&) -> rvalue ref
Foo f;
make_unique(1, f); // make_unique(int, A&&&) -> make_unique(int, A&) -> lvalue ref
make_unique(1, std::move(f)); // make_unique(int, A&&&&) -> make_unique(int, A&&) -> rvalue ref

C++0x rvalue references - lvalues-rvalue binding

This is a follow-on question to
C++0x rvalue references and temporaries
In the previous question, I asked how this code should work:
void f(const std::string &); //less efficient
void f(std::string &&); //more efficient
void g(const char * arg)
{
f(arg);
}
It seems that the move overload should probably be called because of the implicit temporary, and this happens in GCC but not MSVC (or the EDG front-end used in MSVC's Intellisense).
What about this code?
void f(std::string &&); //NB: No const string & overload supplied
void g1(const char * arg)
{
f(arg);
}
void g2(const std::string & arg)
{
f(arg);
}
It seems that, based on the answers to my previous question that function g1 is legal (and is accepted by GCC 4.3-4.5, but not by MSVC). However, GCC and MSVC both reject g2 because of clause 13.3.3.1.4/3, which prohibits lvalues from binding to rvalue ref arguments. I understand the rationale behind this - it is explained in N2831 "Fixing a safety problem with rvalue references". I also think that GCC is probably implementing this clause as intended by the authors of that paper, because the original patch to GCC was written by one of the authors (Doug Gregor).
However, I don't this is quite intuitive. To me, (a) a const string & is conceptually closer to a string && than a const char *, and (b) the compiler could create a temporary string in g2, as if it were written like this:
void g2(const std::string & arg)
{
f(std::string(arg));
}
Indeed, sometimes the copy constructor is considered to be an implicit conversion operator. Syntactically, this is suggested by the form of a copy constructor, and the standard even mentions this specifically in clause 13.3.3.1.2/4, where the copy constructor for derived-base conversions is given a higher conversion rank than other user-defined conversions:
A conversion of an expression of class type to the same class type is given Exact Match rank, and a conversion
of an expression of class type to a base class of that type is given Conversion rank, in spite of the fact that
a copy/move constructor (i.e., a user-defined conversion function) is called for those cases.
(I assume this is used when passing a derived class to a function like void h(Base), which takes a base class by value.)
Motivation
My motivation for asking this is something like the question asked in How to reduce redundant code when adding new c++0x rvalue reference operator overloads ("How to reduce redundant code when adding new c++0x rvalue reference operator overloads").
If you have a function that accepts a number of potentially-moveable arguments, and would move them if it can (e.g. a factory function/constructor: Object create_object(string, vector<string>, string) or the like), and want to move or copy each argument as appropriate, you quickly start writing a lot of code.
If the argument types are movable, then one could just write one version that accepts the arguments by value, as above. But if the arguments are (legacy) non-movable-but-swappable classes a la C++03, and you can't change them, then writing rvalue reference overloads is more efficient.
So if lvalues did bind to rvalues via an implicit copy, then you could write just one overload like create_object(legacy_string &&, legacy_vector<legacy_string> &&, legacy_string &&) and it would more or less work like providing all the combinations of rvalue/lvalue reference overloads - actual arguments that were lvalues would get copied and then bound to the arguments, actual arguments that were rvalues would get directly bound.
Clarification/edit: I realize this is virtually identical to accepting arguments by value for movable types, like C++0x std::string and std::vector (save for the number of times the move constructor is conceptually invoked). However, it is not identical for copyable, but non-movable types, which includes all C++03 classes with explicitly-defined copy constructors. Consider this example:
class legacy_string { legacy_string(const legacy_string &); }; //defined in a header somewhere; not modifiable.
void f(legacy_string s1, legacy_string s2); //A *new* (C++0x) function that wants to move from its arguments where possible, and avoid copying
void g() //A C++0x function as well
{
legacy_string x(/*initialization*/);
legacy_string y(/*initialization*/);
f(std::move(x), std::move(y));
}
If g calls f, then x and y would be copied - I don't see how the compiler can move them. If f were instead declared as taking legacy_string && arguments, it could avoid those copies where the caller explicitly invoked std::move on the arguments. I don't see how these are equivalent.
Questions
My questions are then:
Is this a valid interpretation of the standard? It seems that it's not the conventional or intended one, at any rate.
Does it make intuitive sense?
Is there a problem with this idea that I"m not seeing? It seems like you could get copies being quietly created when that's not exactly expected, but that's the status quo in places in C++03 anyway. Also, it would make some overloads viable when they're currently not, but I don't see it being a problem in practice.
Is this a significant enough improvement that it would be worth making e.g. an experimental patch for GCC?
What about this code?
void f(std::string &&); //NB: No const string & overload supplied
void g2(const std::string & arg)
{
f(arg);
}
...However, GCC and MSVC both reject g2 because of clause 13.3.3.1.4/3, which prohibits lvalues from binding to rvalue ref arguments. I understand the rationale behind this - it is explained in N2831 "Fixing a safety problem with rvalue references". I also think that GCC is probably implementing this clause as intended by the authors of that paper, because the original patch to GCC was written by one of the authors (Doug Gregor)....
No, that's only half of the reason why both compilers reject your code. The other reason is that you can't initialize a reference to non-const with an expression referring to a const object. So, even before N2831 this didn't work. There is simply no need for a conversion because a string is a already a string. It seems you want to use string&& like string. Then, simply write your function f so that it takes a string by value. If you want the compiler to create a temporary copy of a const string lvalue just so you can invoke a function taking a string&&, there wouldn't be a difference between taking the string by value or by rref, would it?
N2831 has little to do with this scenario.
If you have a function that accepts a number of potentially-moveable arguments, and would move them if it can (e.g. a factory function/constructor: Object create_object(string, vector, string) or the like), and want to move or copy each argument as appropriate, you quickly start writing a lot of code.
Not really. Why would you want to write a lot of code? There is little reason to clutter all your code with const&/&& overloads. You can still use a single function with a mix of pass-by-value and pass-by-ref-to-const -- depending on what you want to do with the parameters. As for factories, the idea is to use perfect forwarding:
template<class T, class... Args>
unique_ptr<T> make_unique(Args&&... args)
{
T* ptr = new T(std::forward<Args>(args)...);
return unique_ptr<T>(ptr);
}
...and all is well. A special template argument deduction rule helps differentiating between lvalue and rvalue arguments and std::forward allows you to create expressions with the same "value-ness" as the actual arguments had. So, if you write something like this:
string foo();
int main() {
auto ups = make_unique<string>(foo());
}
the string that foo returned is automatically moved to the heap.
So if lvalues did bind to rvalues via an implicit copy, then you could write just one overload like create_object(legacy_string &&, legacy_vector &&, legacy_string &&) and it would more or less work like providing all the combinations of rvalue/lvalue reference overloads...
Well, and it would be pretty much equivalent to a function taking the parameters by value. No kidding.
Is this a significant enough improvement that it would be worth making e.g. an experimental patch for GCC?
There's no improvement.
I don't quite see your point in this question. If you have a class that is movable, then you just need a T version:
struct A {
T t;
A(T t):t(move(t)) { }
};
And if the class is traditional but has an efficient swap you can write the swap version or you can fallback to the const T& way
struct A {
T t;
A(T t) { swap(this->t, t); }
};
Regarding the swap version, I would rather go with the const T& way instead of that swap. The main advantage of the swap technique is exception safety and is to move the copy closer to the caller so that it can optimize away copies of temporaries. But what do you have to save if you are just constructing the object anyway? And if the constructor is small, the compiler can look into it and can optimize away copies too.
struct A {
T t;
A(T const& t):t(t) { }
};
To me, it doesn't seem right to automatically convert a string lvalue to a rvalue copy of itself just to bind to a rvalue reference. An rvalue reference says it binds to rvalue. But if you try binding to an lvalue of the same type it better fails. Introducing hidden copies to allow that doesn't sound right to me, because when people see a X&& and you pass a X lvalue, I bet most will expect that there is no copy, and that binding is directly, if it works at all. Better fail out straight away so the user can fix his/her code.