I would like to create a std::function bound to a member function taking a rvalue argument. Here is my attempt which does not compile ("xxfunction(154): error C2664: ... You cannot bind an lvalue to an rvalue reference" among others).
class C
{
public:
void F(std::string &&s)
{
//do something with s
}
C(){}
};
C c;
std::function<void(std::string&&)> pF = std::bind(&C::F,&c,std::placeholders::_1);
//somewhere far far away
pF(std::string("test"));
I did some reading and I think it has to do with std::function no using perfect forwarding but I cant figure out how to get it to work.
Edit:
std::function<void(std::string&)> pF = [&c](std::string&in){c.F(std::move(in));};
This is a semi viable work around but it is not perfect because calling pF will work with an lvalue now and move it anyway.
std::string s("test");
pF(s);
auto other = s; //oops
It seems your std::bind implementation does not support perfect forwarding via placeholders, but since you have C++11 and std::bind is ugly anyways, use lambdas:
std::function<void(std::string&&)> pF
= [&c](std::string&& str)
{
c.F(std::move(str));
};
Edit:
Note: Although accepted, this answer is not a solution to the problem at hand, because it is not std::bind but MSVC10's std::function implementation that is flawed. However, the suggestion has led to a workaround and therefore was accepted by PorkyBrain.
Related
Came across an interesting issue today started by my own typo. I created a lambda that takes in a reference to a struct and incorrectly set it to a std::function that receives it's argument by value.
Here's a more concise version:
#include <functional>
struct InputStruct
{
int i;
InputStruct(): i(1){}
};
void function_rcv(std::function<bool(InputStruct)> & func_ref)
{
InputStruct in;
func_ref(in);
}
int main()
{
std::function<bool(InputStruct)> my_func = [](InputStruct & in)->bool{return in.i==1;};
function_rcv(my_func);
}
Checking with godbolt shows this compiles successfully with MSVC, but fails for both Clang and GCC.
Interestingly enough, using a primitive instead of a struct fails compilation on all three compilers.
Is this a bug in the MSVC compiler?
In summary: it is not a compiler bug. MSVC accepts this code because of its default non-conforming behavior, but it can be made standard-conforming with a switch.
First of all, I need to clarify std::function's one aspect: it accepts a function (in general, Callable) which signature is not a perfect match, but the parameters can be converted. Consider:
using intFn = void (int);
void fn(short);
intFn *a = fn; // doesn't compile
std::function<intFn> b = fn; // compiles!
Here, intFn a function type which has an int parameter, while the function fn has a short parameter. The simple function pointer a, cannot be set to point to fn, as the type of the parameter differ (int vs short). But, std::function allows this, so b can be set to point to fn.
In your example, std::function has an InputStruct parameter by value, while the lambda has a non-const lvalue reference InputStruct &. When std::function std::forwards its parameter, it becomes an xvalue, which cannot be bound to the lambda's lvalue reference parameter. That's why standard conforming compilers don't accept this code.
Why does MSVC accept this code? Because it has non-conforming behavior by default: it allows binding class temporaries (and xvalues) to non-const lvalue references. You can disable this behavior with /Zc:referenceBinding (or the older /Za option). If you use this switch, MSVC rejects your example.
Why std::invoke does not work with a pointer to member which is a function object with arguments? Like this:
struct MyClass
{
std::function<void(int)> functor{ [](int arg) { printf("%d\n", arg); } };
};
int main()
{
MyClass mc;
std::invoke(&MyClass::functor, mc, 110);
}
Prints : 'std::invoke': no matching overloaded function found.
I checked this in Visual C++ and g++.
Moreover, std::is_invocable_v<decltype(&MyClass::functor), MyClass, int> claims that this functor is not invocable, which is definitely wrong.
Am I missing something or it is a defect in the standard? If this behavior is correct, then what is the point in std::invoke and all its friends? What I mean is that simple function objects can be easily called without any facilities, but I though the main purpose of std::invoke is to generalize and simplify working with all callables, including the tricky ones, like pointers to members. The fact that std::invoke cannot invoke a clearly invocable target seems weird to me.
The problem is that functor is not a function, but a data member. As such, &MyClass::functor is not a pointer to member function, but a pointer to member data. This distinction means that you cannot pass any other arguments to std::invoke, as you cannot call a data member; but for some data members, like your functor you can. The standard is not clear on this before C++11, and so there was LWG issue 1520 which got merged in C++11.
I mean you can rewrite your example as:
std::invoke(&MyClass::functor, mc)(110);
// or for maximum confusion
std::invoke(std::invoke(&MyClass::functor, mc), 110);
but I don't think that's what you want. Thanks to Barry, this is a bad idea, as what would the following code do:
struct X {
std::function<void()> f;
};
std::invoke(&X::f, x); // gets f, or calls f?
Getting f would make it consistent with other data members, but then you have no way of invoking f if f takes no arguments. Calling f means that you get an inconsistency with other data members when you just want to get them.
As I understand it,
std::bind perfectly forwards both the callable object it wraps and the arguments to that callable object;
the std::bind return object is itself movable and/or copyable, depending on whether the callable object and its arguments are movable and/or copyable;
a std::bind return object may be nested, in which case the outer std::bind return object is movable and/or copyable, just as when binding other callable objects.
Therefore, I would expect the following code snippet to compile okay. Instead, the code generates a spew of compiler errors at the last two statements in main().
#include <functional>
template<typename HandlerType>
void call_handler(HandlerType&& handler)
{
handler();
}
template<typename HandlerType>
void do_something(HandlerType&& handler)
{
auto f = std::bind(
&call_handler<HandlerType&>,
std::forward<HandlerType>(handler));
f();
}
int main()
{
auto a = [&]() {};
do_something(a);
do_something(std::move(a));
auto b = std::bind([&]() {});
do_something(b); // <- compiler error!
do_something(std::move(b)); // <- compiler error!
}
Each of the two problem line spews errors without the other. To eliminate all errors, I must comment out both lines.
Here's a sample error, from g++ 4.9.2 in Cygwin, at the call to f() in do_something():
(4 of 103): error: no match for call to ‘(std::_Bind<void (*(std::_Bind<main()::<lambda()>()>))(std::_Bind<main()::<lambda()>()>&)>) ()’
Here's a sample error from Visual Studio 2013, at the same line:
1>C:\Program Files (x86)\Microsoft Visual Studio12.0\VC\include\functional(1149): error C2664: 'void (HandlerType)' : cannot convert argument 1 from 'void' to 'std::_Bind<false,void,main::<lambda_2b8ed726b4f655ffe5747e5b66152230>,> '
What's going on? Do I misunderstand std::bind?
Specifically, how can I
bind a callable object? and
pass that std::bind return object to a function taking a universal reference? and
nest that std::bind return object in another std::bind?
My goal is for the underlying callable object and its arguments to be perfectly forwarded.
EDIT: To clarify, I want to pass the wrapped callable object and its arguments by value, not by reference, so std::ref won't help—at least, not as a full solution. The reason is that my real code is more complex and involves passing the f std::bind return object across a thread boundary, and both the a and b std::bind return objects may go out of scope in the original thread before call_handler calls f(), so a and b need to copy or move into f, not be mere references. That said, my question is specifically about std::bind and perfect forwarding, and for the purpose of asking a good question, I've distilled out everything not needed to reproduce the specific compiler errors I mentioned.
Your assumption 1 is wrong, bind always passes the bound arguments as lvalues to the callable it is wrapping. To demonstrate this, change the bind expression within do_something to the following
auto f = std::bind(
&call_handler<decltype(handler)>,
std::forward<HandlerType>(handler));
The following line will then fail to compile
do_something(std::move(a));
because decltype(handler) is an rvalue reference, but bind will try to call call_handler with an lvalue reference to the bound lambda expression you passed it in main.
Now for what's going wrong in the second half of your example. bind has special handling for nested bind expressions, which it will recognize and evaluate. However, in your example, you don't want that to happen. Instead, you want the nested bind to be forwarded as is to call_handler, which will then invoke it.
Boost provides boost::protect which lets you mask the real type of the nested bind and thus prevent its evaluation by the outer bind.
Unfortunately, there is no std::protect equivalent, but it's not difficult to write it yourself.
template<typename T>
struct protect_wrapper : T
{
protect_wrapper(const T& t) : T(t)
{}
protect_wrapper(T&& t) : T(std::move(t))
{}
};
template<typename T>
std::enable_if_t<!std::is_bind_expression<std::decay_t<T>>::value,
T&&
>
protect(T&& t)
{
return std::forward<T>(t);
}
template<typename T>
std::enable_if_t<std::is_bind_expression<std::decay_t<T>>::value,
protect_wrapper<std::decay_t<T>>
>
protect(T&& t)
{
return protect_wrapper<std::decay_t<T>>(std::forward<T>(t));
}
Just wrap your inner bind expression with protect, and your code will compile.
auto b = protect(std::bind([&]() {}));
do_something(b);
do_something(std::move(b));
Live demo
I was reading a good tutorial on lvalue/rvalue references. If I've understood correctly when there is type deduction something like T&& can accept both an lvalue and an rvalue.
But is there a way to achieve that without a generic class? I'd like to avoid duplicating all my methods for accepting both lvalues and rvalues. And of course avoid passing big objects by value.
r-value references are mostly use in move-constructor and move assignment.
For regular method, you may stick with one reference type only:
For read only parameter (without copy), const reference is enough.
if you have to do a copy, you may take your argument by value and use std::move:
Example:
class Test
{
public:
void displayString(const std::string& s) const { std::cout << s << m_s; }
void setString(std::string s) { m_s = std::move(s); }
private:
std::string m_s;
};
If the function that you implement does not need rvalue semantic, then you can simply pass the argument by reference or by constant reference.
However, if you can take advantage of rvalues and do not want to duplicate your code, you can pass by value and move the result. That should be almost as efficient and can be more maintainable than code duplication or an implementation with universal references.
This answer shows the technique: Should all/most setter functions in C++11 be written as function templates accepting universal references?
// copy, then move
void set_a(A a_) { a = std::move(a_); }
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.