How to store either rvalue or lvalue references in template - c++

I am trying to create a simple template enumerator class that should accept any object over which : operator is defined and later on print pairs of the form (i, v[i]). A simple implementation is the following:
template<typename T>
struct enumerator {
T &v; // reference to minimize copying
enumerator(T &_v) : v(_v) {}
void do_enumerate() {
size_t i = 0;
for(auto x : v) {
cout << i << x << endl;
i++;
}
}
};
This works ok for things like:
Case A
vector<int> v({1,2,6,2,4});
auto e = enumerator(v);
e.do_enumerate();
However, I would also like it to handle temporary objects like:
Case B
auto e = enumerator(vector<int>({2,3,9});
e.do_enumerate();
This does not work and the compiler throws:
no matching function for call to ‘enumerator<std::vector<int> >::enumerator(std::vector<int>)
So, I tried to then add a
enumerator(T _t) : t(_T) {}
constructor to resolve this error. Now case A does not work and there is an error:
error: call of overloaded ‘enumerator(std::vector<int>&)’ is ambiguous
Moreover, in case B, the output of the enumeration is not correct.
What is the cleanest way to solve this? I would
really like both cases to be working
prefer not to use any libraries other than stdc++
want as little copying as possible (thus just storing a T t in the struct is not an option)
C++11 is not a problem. I have g++-4.8, which I presume has complete enough C++11 support.

Well I would like to copy in case the argument is an rvalue, and not copy in case it is not. Is that possible?
This can be accomplished using a make_enumerator helper function as shown.
template <class T>
struct enumerator {
T v;
enumerator(T&& _v) : v(std::forward<T>(_v)) {}
void do_enumerate() {
size_t i = 0;
for(auto x : v) {
cout << i << x << endl;
i++;
}
}
};
template <class T>
enumerator<T> make_enumerator(T&& x) {
return enumerator<T>(std::forward<T>(x));
}
int main() {
vector<int> v {5, 2, 9, 1};
make_enumerator(v).do_enumerate();
make_enumerator(std::move(v)).do_enumerate();
}
How does this work?
If the argument to make_enumerator is an lvalue of type A then T is deduced as A& and we get the enumerator enumerator<A&>, whereas if it is an rvalue of type A then T is deduced as A and we get the enumerator enumerator<A>.
In the first case the member enumerator::v will have type A&, an lvalue reference that binds to the constructor argument (no copying). In the second case the member will have type A. The use of std::forward casts the parameter _v to an rvalue, so it will be moved from when it is used to initialize v.

This is a classic example where you don't actually need a class/struct (which actually introduce useless code) and you can just use good old functions:
template<typename Container>
void enumerate(const Container& t) {
std::size_t i = 0;
for(auto it = t.begin(); it != t.end(); ++it, ++i)
std::cout << i << *it << std::endl;
}
and then call it as:
enumerate(std::vector<int>{2,3,9});
Live demo
With this method you also get argument type inference for free (which you don't get with a struct).

Related

C++ confusing closure captures [v] vs [v = v]

In the following code, it seems that the compiler sometimes prefer to call the templated constructor and fails to compile when a copy constructor should be just fine. The behavior seems to change depending on whether the value is captured as [v] or [v = v], I thought those should be exactly the same thing. What am I missing?
I'm using gcc 11.2.0 and compiling it with "g++ file.cpp -std=C++17"
#include <functional>
#include <iostream>
#include <string>
using namespace std;
template <class T>
struct record {
explicit record(const T& v) : value(v) {}
record(const record& other) = default;
record(record&& other) = default;
template <class U>
record(U&& v) : value(forward<U>(v)) {} // Removing out this constructor fixes print1
string value;
};
void call(const std::function<void()>& func) { func(); }
void print1(const record<string>& v) {
call([v]() { cout << v.value << endl; }); // This does not compile, why?
}
void print2(const record<string>& v) {
call([v = v]() { cout << v.value << endl; }); // this compiles fine
}
int main() {
record<string> v("yo");
print1(v);
return 0;
}
I don't disagree with 康桓瑋's answer, but I found it a little hard to follow, so let me explain it with a different example. Consider the following program:
#include <functional>
#include <iostream>
#include <typeinfo>
#include <type_traits>
struct tracer {
tracer() { std::cout << "default constructed\n"; }
tracer(const tracer &) { std::cout << "copy constructed\n"; }
tracer(tracer &&) { std::cout << "move constructed\n"; }
template<typename T> tracer(T &&t) {
if constexpr (std::is_same_v<T, const tracer>)
std::cout << "template constructed (const rvalue)\n";
else if constexpr (std::is_same_v<T, tracer&>)
std::cout << "template constructed (lvalue)\n";
else
std::cout << "template constructed (other ["
<< typeid(T).name() << "])\n";
}
};
int
main()
{
using fn_t = std::function<void()>;
const tracer t;
std::cout << "==== value capture ====\n";
fn_t([t]() {});
std::cout << "==== init capture ====\n";
fn_t([t = t]() {});
}
When run, this program outputs the following:
default constructed
==== value capture ====
copy constructed
template constructed (const rvalue)
==== init capture ====
copy constructed
move constructed
So what's going on here? First, note in both cases, the compiler must materialize a temporary lambda object to pass into the constructor for fn_t. Then, the constructor of fn_t must make a copy of the lambda object to hold on to it. (Since in general the std::function may outlive the lambda that was passed in to its constructor, it cannot retain the lambda by reference only.)
In the first case (value capture), the type of the captured t is exactly the type of t, namely const tracer. So you can think of the unnamed type of the lambda object as some kind of compiler-defined struct that contains a field of type const tracer. Let's give this structure a fake name of LAMBDA_T. So the argument to the constructor to fn_t is of type LAMBDA_T&&, and an expression that accesses the field inside is consequently of type const tracer&&, which matches the template constructor's forwarding reference better than the actual copy constructor. (In overload resolution rvalues prefer binding to rvalue references over binding to const lvalue references when both are available.)
In the second case (init capture), the type of the captured t = t is equivalent to the type of tnew in a declaration like auto tnew = t, namely tracer. So now the field in our internal LAMBDA_T structure is going to be of type tracer rather than const tracer, and when an argument of type LAMBDA_T&& to fn_t's constructor must be move-copied, the compiler will choose tracer's normal move constructor for moving that field.
For [v], the type of the lambda internal member variable v is const record, so when you
void call(const std::function<void()>&);
void print1(const record<string>& v) {
call([v] { });
}
Since [v] {} is a prvalue, when it initializes const std::function&, v will be copied with const record&&, and the template constructor will be chosen because it is not constrained.
In order to invoke v's copy constructor, you can do
void call(const std::function<void()>&);
void print1(const record<string>& v) {
auto l = [v] { };
call(l);
}
For [v=v], the type of the member variable v inside the lambda is record, so when the prvalue lambda initializes std::function, it will directly invoke the record's move constructor since record&& better matches.

Implicitly cast wrapper class to supperclass in templated call

In designing a DSL (which compiles into C++), I found it convenient to define a wrapper class that, uppon destruction, would call a .free() method on the contained class:
template<class T>
class freeOnDestroy : public T {
using T::T;
public:
operator T&() const { return *this; }
~freeOnDestroy() { T::free(); }
};
The wrapper is designed to be completely transparent: All methods, overloads and constructors are inherited from T (at least to my knowledge), but when included in the wrapper, the free() method is called uppon destruction. Note that I explicitly avoid using T's destructor for this since T::free() and ~T() may have different semantics!
All this works fine, untill a wrapped class gets used as a member to a non-reference templated call, at which point freeOnDestroy is instantiated, calling free on the wrapped object. What I would like to happen is for the tempated method to use T instead of freeOnDestroy<T>, and to implicitly cast the parameter into the supperclass. The following code sample illustrates this problem:
// First class that has a free (and will be used in foo)
class C{
int * arr;
public:
C(int size){
arr = new int[size];
for (int i = 0; i < size; i++) arr[i] = i;
}
int operator[] (int idx) { return arr[idx]; }
void free(){ cout << "free called!\n"; delete []arr; }
};
// Second class that has a free (and is also used in foo)
class V{
int cval;
public:
V(int cval) : cval(cval) {}
int operator[] (int idx) { return cval; }
void free(){}
};
// Foo: in this case, accepts anything with operator[int]
// Foo cannot be assumed to be written as T &in!
// Foo in actuality may have many differently-templated parameters, not just one
template<typename T>
void foo(T in){
for(int i = 0; i < 5; i++) cout << in[i] << ' ';
cout << '\n';
}
int main(void){
C c(15);
V v(1);
freeOnDestroy<C> f_c(15);
foo(c); // OK!
foo(v); // OK!
foo<C>(f_c); // OK, but the base (C) of f_c may not be explicitly known at the call site, for example, if f_c is itself received as a template
foo(f_c); // BAD: Creates a new freeOnDestroy<C> by implicit copy constructor, and uppon completion calls C::free, deleting arr! Would prefer it call foo<C>
foo(f_c); // OH NO! Tries to print arr, but it has been deleted by previous call! Segmentation fault :(
return 0;
}
A few non solutions I should mention are:
Making freeOnDestroy::freeOnDestroy(const freeOnDestroy &src) explicit and private, but this seems to override T's constructor. I'd hoped it would try to implicitly convert it to T and use that as the template argument.
Assume foo receives a reference of its templated arguments (as in void foo(T &in): This is neither the case, nor desirable in some cases
Always explicitly template the call to foo, as in foo<C>(f_c): f_c itself may be templated, so it's hard to know to instantiate foo with C (yes, this could be done with creating multiple versions of foo, to remove the wrappers one by one, but I can't find a way of doing that without creating a different overload for each templated argument of foo).
In summary, my question is: Is there a clean(ish) method to ensure a base class will be casted to its superclass when resolving a template? Or, if not, is there some way of using SFINAE, by causing a substitution failure when the template argument is an instance of the wrapper class, and thus force it to use the implicit cast to the wrapped class (without duplicating each foo-like method signature possibly dozens of times)?
I presently have a work-arround that involves changes in the DSL, but I'm not entirely happy with it, and was curious if it was at all possible to design a wrapper class that works as described.
The problem here not when "wrapped class gets used as a member to a non-reference templated call".
The problem here is that the template wrapper -- and likely its superclass too -- has violated the Rule Of Three.
Passing an instance of the class as a non-reference parameter is just another way of saying "passing by value". Passing by value makes a copy of the instance of the class. Neither your template class -- nor its wrapped class, most likely -- has an explicit copy constructor; as such the copied instance of the class has no knowledge that it is a copy, hence the destructor does what it thinks it should do.
The correct solution here is not to hack something up that makes passing an instance of freeOnDestroy<T> by value end up copying T, rather than freeOnDestroy<T>. The correct solution is to add a proper copy-constructor and the assignment operator to both the freeOnDestroy template, and possibly any superclass that uses it, so that everything complies with the Rule Of Three.
You can use a properly defined detector and a sfinaed function, as it follows:
#include<iostream>
#include<type_traits>
template<class T>
class freeOnDestroy : public T {
using T::T;
public:
operator T&() const { return *this; }
~freeOnDestroy() { T::free(); }
};
template<typename T>
struct FreeOnDestroyDetector: std::false_type { };
template<typename T>
struct FreeOnDestroyDetector<freeOnDestroy<T>>: std::true_type { };
class C{
int * arr;
public:
C(int size){
arr = new int[size];
for (int i = 0; i < size; i++) arr[i] = i;
}
int operator[] (int idx) { return arr[idx]; }
void free(){ std::cout << "free called!\n"; delete []arr; }
};
class V{
int cval;
public:
V(int cval) : cval(cval) {}
int operator[] (int idx) { return cval; }
void free(){}
};
template<typename..., typename T>
std::enable_if_t<not FreeOnDestroyDetector<std::decay_t<T>>::value>
foo(T in) {
std::cout << "here you have not a freeOnDestroy based class" << std::endl;
}
template<typename..., typename T>
std::enable_if_t<FreeOnDestroyDetector<std::decay_t<T>>::value>
foo(T &in) {
std::cout << "here you have a freeOnDestroy based class" << std::endl;
}
int main(void){
C c(15);
V v(1);
freeOnDestroy<C> f_c(15);
foo(c);
foo(v);
foo<C>(f_c);
foo(f_c);
foo(f_c);
return 0;
}
As you can see by running the example, free is called only once, that is for the freeOnDestroy created in the main function.
If you want to forbid definitely freeOnDestroy as a parameter, you can use a single function as the following one:
template<typename..., typename T>
void foo(T &in) {
static_assert(not FreeOnDestroyDetector<std::decay_t<T>>::value, "!");
std::cout << "here you have a freeOnDestroy based class" << std::endl;
}
Note that I added a variadic parameter as a guard, so that one can no longer use foo<C>(f_c); to force a type to be used.
Remove it if you want to allow such an expression. It was not clear from the question.
One solution, which, although a little ugly, seems to work, is to use an overloaded unwrapping method, such as:
template<typename T> T freeOnDestroyUnwrapper(const T &in){ return in; }
template<typename T> T freeOnDestroyUnwrapper(const freeOnDestroy<T> &in){ return in; }
template<typename T> T freeOnDestroyUnwrapper(const freeOnDestroy<typename std::decay<T>::type> &in){ return in; }
template<typename T> T& freeOnDestroyUnwrapper(T &in){ return in; }
template<typename T> T& freeOnDestroyUnwrapper(freeOnDestroy<T> &in){ return in; }
template<typename T> T& freeOnDestroyUnwrapper(freeOnDestroy<typename std::decay<T>::type> &in){ return in; }
Then, calls can be made using the unwrapper:
int main(void){
C c(15);
V v(1);
freeOnDestroy<C> f_c(15);
foo(freeOnDestroyUnwrapper(c));
foo(freeOnDestroyUnwrapper(v));
foo<C>(freeOnDestroyUnwrapper(f_c));
foo(freeOnDestroyUnwrapper(f_c));
foo(freeOnDestroyUnwrapper(f_c));
return 0;
}
Or, to make this less verbose, we can alter foo so it does this for us:
template<typename T>
void _foo(T in){
for(int i = 0; i < 5; i++) cout << in[i] << ' ';
cout << '\n';
}
template<typename... Ts>
void foo(Ts&&... args){
_foo(freeOnDestroyUnwrapper(args)...);
}
And then call it as normal:
int main(void){
C c(15);
V v(1);
freeOnDestroy<C> f_c(15);
foo(c);
foo(v);
//foo<C>(f_c); // This now doesn't work!
foo(f_c);
foo(f_c);
return 0;
}
This seems to work for any number of arguments foo may have (of different templates, if needed), and seems to behave appropriately when foos input is a reference (which does not occur in my context, but would be good for the sake of making this solution generic).
I'm not convinced that this is the best solution, or that it generalizes to every case, plus, having to double all declarations is a bit cumbersome, and opaque to most IDEs autocomplete features. Better solutions and improvements are welcome!

std::tuple for non-copyable and non-movable object

I have a class with copy & move ctor deleted.
struct A
{
A(int a):data(a){}
~A(){ std::cout << "~A()" << this << " : " << data << std::endl; }
A(A const &obj) = delete;
A(A &&obj) = delete;
friend std::ostream & operator << ( std::ostream & out , A const & obj);
int data;
};
And I want to create a tuple with objects of this class. But the following does not compile:
auto p = std::tuple<A,A>(A{10},A{20});
On the other hand, the following does compile, but gives a surprising output.
int main() {
auto q = std::tuple<A&&,A&&>(A{100},A{200});
std::cout << "q created\n";
}
Output
~A()0x22fe10 : 100
~A()0x22fe30 : 200
q created
It means that dtor for objects is called as soon as tuple construction line ends. So, what is significance of a tuple of destroyed objects?
This is bad:
auto q = std::tuple<A&&,A&&>(A{100},A{200});
you are constructing a tuple of rvalue references to temporaries that get destroyed at the end of the expression, so you're left with dangling references.
The correct statement would be:
std::tuple<A, A> q(100, 200);
However, until quite recently, the above was not supported by the standard. In N4296, the wording around the relevant constructor for tuple is [tuple.cnstr]:
template <class... UTypes>
constexpr explicit tuple(UTypes&&... u);
Requires: sizeof...(Types) == sizeof...(UTypes). is_constructible<Ti, Ui&&>::value is true
for all i.
Effects: Initializes the elements in the tuple with the corresponding value in std::forward<UTypes>(u).
Remark: This constructor shall not participate in overload resolution unless each type in UTypes is
implicitly convertible to its corresponding type in Types.
So, this constructor was not participating in overload resolution because int is not implicitly convertible to A. This has been resolved by the adoption of Improving pair and tuple, which addressed precisely your use-case:
struct D { D(int); D(const D&) = delete; };
std::tuple<D> td(12); // Error
The new wording for this constructor is, from N4527:
Remarks: This constructor shall not participate in overload resolution unless sizeof...(Types) >= 1 and is_constructible<Ti, Ui&&>::value is true for all i. The constructor is explicit if and only
if is_convertible<Ui&&, Ti>::value is false for at least one i.
And is_constructible<A, int&&>::value is true.
To present the difference another way, here is an extremely stripped down tuple implementation:
struct D { D(int ) {} D(const D& ) = delete; };
template <typename T>
struct Tuple {
Tuple(const T& t)
: T(t)
{ }
template <typename U,
#ifdef USE_OLD_RULES
typename = std::enable_if_t<std::is_convertible<U, T>::value>
#else
typename = std::enable_if_t<std::is_constructible<T, U&&>::value>
#endif
>
Tuple(U&& u)
: t(std::forward<U>(u))
{ }
T t;
};
int main()
{
Tuple<D> t(12);
}
If USE_OLD_RULES is defined, the first constructor is the only viable constructor and hence the code will not compile since D is noncopyable. Otherwise, the second constructor is the best viable candidate and that one is well-formed.
The adoption was recent enough that neither gcc 5.2 nor clang 3.6 actually will compile this example yet. So you will either need a newer compiler than that (gcc 6.0 works) or come up with a different design.
Your problem is that you explicitly asked for a tuple of rvalue references, and a rvalue reference is not that far from a pointer.
So auto q = std::tuple<A&&,A&&>(A{100},A{200}); creates two A objects, takes (rvalue) references to them, build the tuple with the references... and destroys the temporary objects, leaving you with two dangling references
Even if it is said to be more secure than good old C and its dangling pointers, C++ still allows programmer to write wrong programs.
Anyway, the following would make sense (note usage of A& and not A&&):
int main() {
A a(100), b(100); // Ok, a and b will leave as long as main
auto q = tuple<A&, A&>(a, b); // ok, q contains references to a and b
...
return 0; // Ok, q, a and b will be destroyed
}

C++ why does passing an lvalue to a move constructor work for templates?

I have this code, which doesn't compile, which is expected.
This is the error: an rvalue reference cannot be bound to an lvalue
class SomeData
{
public:
vector<int> data;
SomeData()
{
cout << "SomeData ctor" << endl;
data.push_back(1);
data.push_back(2);
data.push_back(3);
}
SomeData(const SomeData &other)
{
cout << "SomeData copy ctor" << endl;
data = other.data;
}
SomeData(SomeData &&other)
{
cout << "SomeData move ctor" << endl;
data = move(other.data);
}
~SomeData()
{
cout << "SomeData dtor" << endl;
}
void Print() const
{
for(int i : data)
cout << i;
cout << endl;
}
};
void Function(SomeData &&someData)
{
SomeData localData(someData);
localData.Print();
}
int main(int argc, char *argv[])
{
SomeData data;
Function(data); // ERROR
data.Print();
return 0;
}
But, when I turn Function() into a template, it works fine, and uses the copy constructor of SomeData instead.
template<class T>
void Function(T &&someData)
{
T localData(someData); // no more error
localData.Print();
}
Is this standard C++ behaviour?
I've noticed that visual studio tends to be more forgiving when it comes to templates, so I am wondering if I can expect this same behaviour from all compliant C++11 compilers.
Yes. In the case of a template function, the compiler deduces the template argument T such that it matches the argument given.
Since someData is in fact an lvalue, T is deduced as SomeData &. The declaration of Function, after type deduction, then becomes
void Function(SomeData & &&)
and SomeData & &&, following the rules for reference collapsing, becomes SomeData &.
Hence, the function argument someData becomes an lvalue-reference and is passed as such to the initialization of localData. Note that (as #aschepler pointed out correctly) localData is declared as T, so it is itself a reference of type SomeData &. Hence, no copy construction happens here – just the initialization of a reference.
If you want localData to be an actual copy, you would have to turn the type from SomeData & into SomeData, i.e. you would have to remove the & from the type. You could do this using std::remove_reference:
template<class T>
void Function(T &&someData)
{
/* Create a copy, rather than initialize a reference: */
typename std::remove_reference<T>::type localData(someData);
localData.Print();
}
(For this, you'd have to #include <type_traits>.)
It is indeed intended behavior. Template functions of the form:
template< class T >
Ret Function( T&& param )
{
...
}
follows special rules (Ret can be or not a template, it doesn't matter). T&& is called a universal reference and it can basically bind to anything. This is because when template deduction kicks in and the param is in that form (beware, vector<T>&& is not a universal reference, neither is C<T> for any other template parameter), the reference collapsing rule is applied:
T = int& => T&& = int& && and that collapse to a single int&
the complete table of corrispondence is:
& + && = &
&& + & = &
&& + && = &&
So when you have the above function
int a = 5;
int b& = a;
Function( a ); // (1)
Function( b ); // (2)
Function( 3 ); // (3)
In case 1, T = int& and the deduced type is int& (since a is an lvalue) so Function has the following signature:
Ret Function( int& param ) // int& && collapses to int&
In case 2, T = int&
Ret Function( int& param ) // int& && collapses to int&
In case 3, T = int
Ret Function( int&& param )
This collapsing rule is what the committee found out to be reasonable to make perfect forwarding works. You can find the long story in this Scott Meyers's video
Just to reassure you: this is not a MSVC problem, this is actually expected behaviour.
In templates, && has a different meaning when applied to template type parameters. It's called an universal reference.
I could probably paraphrase, but this article explains it very nicely so you should just read it.
To sum it up wildly (and very imprecisely), universal references have the ability to "decay" into ordinary references if the need arises.

Passing rvalues through std::bind

I want to pass an rvalue through std::bind to a function that takes an rvalue reference in C++0x. I can't figure out how to do it. For example:
#include <utility>
#include <functional>
template<class Type>
void foo(Type &&value)
{
Type new_object = std::forward<Type>(value); // move-construct if possible
}
class Movable
{
public:
Movable(Movable &&) = default;
Movable &operator=(Movable &&) = default;
};
int main()
{
auto f = std::bind(foo<Movable>, Movable());
f(); // error, but want the same effect as foo(Movable())
}
The reason this fails is because when you specify foo<Movable>, the function you're binding to is:
void foo(Movable&&) // *must* be an rvalue
{
}
However, the value passed by std::bind will not be an rvalue, but an lvalue (stored as a member somewhere in the resulting bind functor). That, is the generated functor is akin to:
struct your_bind
{
your_bind(Movable arg0) :
arg0(arg0)
{}
void operator()()
{
foo<int>(arg0); // lvalue!
}
Movable arg0;
};
Constructed as your_bind(Movable()). So you can see this fails because Movable&& cannot bind to Movable.†
A simple solution might be this instead:
auto f = std::bind(foo<Movable&>, Movable());
Because now the function you're calling is:
void foo(Movable& /* conceptually, this was Movable& &&
and collapsed to Movable& */)
{
}
And the call works fine (and, of course, you could make that foo<const Movable&> if desired). But an interesting question is if we can get your original bind to work, and we can via:
auto f = std::bind(foo<Movable>,
std::bind(static_cast<Movable&&(&)(Movable&)>(std::move<Movable&>),
Movable()));
That is, we just std::move the argument before we make the call, so it can bind. But yikes, that's ugly. The cast is required because std::move is an overloaded function, so we have to specify which overload we want by casting to the desired type, eliminating the other options.
It actually wouldn't be so bad if std::move wasn't overloaded, as if we had something like:
Movable&& my_special_move(Movable& x)
{
return std::move(x);
}
auto f = std::bind(foo<Movable>, std::bind(my_special_move, Movable()));
Which is much simpler. But unless you have such a function laying around, I think it's clear you probably just want to specify a more explicit template argument.
† This is different than calling the function without an explicit template argument, because explicitly specifying it removes the possibility for it to be deduced. (T&&, where T is a template parameter, can be deduced to anything, if you let it be.)
You could use a lambda expression.
auto f = [](){ foo(Movable()); };
This would seem to be the simplest option.
Guys i have hacked up a perfect forwarding version of a binder(limited to 1 param) here
http://code-slim-jim.blogspot.jp/2012/11/stdbind-not-compatable-with-stdmove.html
For reference the code is
template <typename P>
class MovableBinder1
{
typedef void (*F)(P&&);
private:
F func_;
P p0_;
public:
MovableBinder1(F func, P&& p) :
func_(func),
p0_(std::forward<P>(p))
{
std::cout << "Moved" << p0_ << "\n";
}
MovableBinder1(F func, P& p) :
func_(func),
p0_(p)
{
std::cout << "Copied" << p0_ << "\n";
}
~MovableBinder1()
{
std::cout << "~MovableBinder1\n";
}
void operator()()
{
(*func_)(std::forward<P>(p0_));
}
};
As u can see from the above proof of concept, its very possible...
I see no reason why std::bind is incompatible with std::move... std::forward is after all for perfect forwarding I dont understand why there isnt a std::forwarding_bind ???
(This is actually a comment to GMan's answer, but I need some formatting for the code).
If generated functor actually is like this:
struct your_bind
{
your_bind(Movable arg0) :
arg0(arg0)
{}
void operator()()
{
foo(arg0);
}
Movable arg0;
};
then
int main()
{
auto f = your_bind(Movable());
f(); // No errors!
}
compliles without errors. as it's possible to assign and initialize data with rvalue and then pass a data value to rvalue argument of the foo(). However, I suppose that bind implementation extracts function argument type directly from foo() signature. i.e. the generated functor is:
struct your_bind
{
your_bind(Movable && arg0) :
arg0(arg0) // **** Error:cannot convert from Movable to Movable &&amp
{}
void operator()()
{
foo(arg0);
}
Movable&& arg0;
};
and indeed, this really fails to initialize rvalue data member.
Perhaps,the bind implpementation simply does not correctly extract "unreferenced" type from function argument type and uses this type for functor's data member declaration "as is", without trimming &&.
the correct functor should be:
struct your_bind
{
your_bind(Movable&& arg0) :
arg0(arg0)
{}
void operator()()
{
foo(arg0);
}
Movable arg0; // trim && !!!
};
One more improvement in GManNickG's answer and I've got pretty solution:
auto f = std::bind(
foo<Movable>,
std::bind(std::move<Movable&>, Movable())
);
(works in gcc-4.9.2 and msvc2013)